From 0f9e0c9c7670d7e8442b4fe79632207f37173a4b Mon Sep 17 00:00:00 2001 From: BennyKok Date: Thu, 25 Jan 2024 00:34:41 +0800 Subject: [PATCH] feat: pricing plan + usage page --- web/bun.lockb | Bin 498007 -> 499775 bytes web/drizzle/0035_fearless_golden_guardian.sql | 14 + web/drizzle/0036_flippant_meltdown.sql | 22 + web/drizzle/0037_eager_cyclops.sql | 3 + web/drizzle/0038_yummy_darkhawk.sql | 1 + web/drizzle/0039_nostalgic_lyja.sql | 2 + web/drizzle/0040_salty_archangel.sql | 1 + web/drizzle/0041_thick_norrin_radd.sql | 1 + web/drizzle/meta/0035_snapshot.json | 894 +++++++++++++++ web/drizzle/meta/0036_snapshot.json | 970 ++++++++++++++++ web/drizzle/meta/0037_snapshot.json | 984 ++++++++++++++++ web/drizzle/meta/0038_snapshot.json | 989 ++++++++++++++++ web/drizzle/meta/0039_snapshot.json | 1001 ++++++++++++++++ web/drizzle/meta/0040_snapshot.json | 1007 ++++++++++++++++ web/drizzle/meta/0041_snapshot.json | 1013 +++++++++++++++++ web/drizzle/meta/_journal.json | 51 +- web/package.json | 3 + .../app/(app)/api/stripe/callback/route.tsx | 175 +++ .../app/(app)/api/stripe/checkout/route.tsx | 46 + .../app/(app)/api/stripe/dashboard/route.tsx | 41 + web/src/app/(app)/api/update-run/route.ts | 94 +- .../pricing/components/gpuPricingTable.tsx | 81 -- .../pricing/components/pricePlanList.tsx | 157 --- web/src/app/(app)/pricing/const/Icon.tsx | 37 - web/src/app/(app)/pricing/page.tsx | 6 +- web/src/app/(app)/providers.tsx | 16 +- web/src/app/(app)/usage/loading.tsx | 9 + web/src/app/(app)/usage/page.tsx | 57 + web/src/components/Navbar.tsx | 23 +- web/src/components/PricingPlan.tsx | 381 +++++++ web/src/components/ui/progress.tsx | 28 + web/src/db/schema.ts | 31 + web/src/server/APIKeyBodyRequest.ts | 2 +- web/src/server/createRun.ts | 12 +- web/src/server/editWorkflowOnMachine.tsx | 7 +- web/src/server/getCurrentPlan.tsx | 32 + web/src/server/getUrlServerSide.tsx | 10 + web/src/server/linkToPricing.ts | 45 - web/src/server/stripe.ts | 3 + 39 files changed, 7847 insertions(+), 402 deletions(-) create mode 100644 web/drizzle/0035_fearless_golden_guardian.sql create mode 100644 web/drizzle/0036_flippant_meltdown.sql create mode 100644 web/drizzle/0037_eager_cyclops.sql create mode 100644 web/drizzle/0038_yummy_darkhawk.sql create mode 100644 web/drizzle/0039_nostalgic_lyja.sql create mode 100644 web/drizzle/0040_salty_archangel.sql create mode 100644 web/drizzle/0041_thick_norrin_radd.sql create mode 100644 web/drizzle/meta/0035_snapshot.json create mode 100644 web/drizzle/meta/0036_snapshot.json create mode 100644 web/drizzle/meta/0037_snapshot.json create mode 100644 web/drizzle/meta/0038_snapshot.json create mode 100644 web/drizzle/meta/0039_snapshot.json create mode 100644 web/drizzle/meta/0040_snapshot.json create mode 100644 web/drizzle/meta/0041_snapshot.json create mode 100644 web/src/app/(app)/api/stripe/callback/route.tsx create mode 100644 web/src/app/(app)/api/stripe/checkout/route.tsx create mode 100644 web/src/app/(app)/api/stripe/dashboard/route.tsx delete mode 100644 web/src/app/(app)/pricing/components/gpuPricingTable.tsx delete mode 100644 web/src/app/(app)/pricing/components/pricePlanList.tsx delete mode 100644 web/src/app/(app)/pricing/const/Icon.tsx create mode 100644 web/src/app/(app)/usage/loading.tsx create mode 100644 web/src/app/(app)/usage/page.tsx create mode 100644 web/src/components/PricingPlan.tsx create mode 100644 web/src/components/ui/progress.tsx create mode 100644 web/src/server/getCurrentPlan.tsx create mode 100644 web/src/server/getUrlServerSide.tsx delete mode 100644 web/src/server/linkToPricing.ts create mode 100644 web/src/server/stripe.ts diff --git a/web/bun.lockb b/web/bun.lockb index 650dd43bf9f70e00173efe1b412186dd13171118..ed42cf30664004b10056a212496a5649d148de8b 100755 GIT binary patch delta 94506 zcmeFadz_Wy!vDY4s#SAKsB{{pgi;YjHB(bFLOP$QG{eL+P0iGtnnO*b zL6n3fN}@JVn~-A-q3u*?6QU5m_vgN@8MF8H?C1IJ@ALcp^J~4#e6G*?Iv?-*UTaO> zd!p6z8(ZCeW{0~AeqPX~)8I$5jz25$(dAdI=w2Gv>WBKrzjn`}_2*tVCe-t>d+Uev zs+@O8>$1gu-N4viM~6b?SC$kNr{|3iy&DaMn&S&I(=&>R_Una0ivI@nlrDdKkg233 zI|$4teFOL_6sY)aF;?fmm2WzF9C`wgEzo1ohGhgI1e73)1dY&9XcJVWs=%U>jKcJy z%+NU`Iv!t;U6@{+Srp2>(l)wrLz}KRD>E;9!t~J3q*J~qod3#C#;e?kIr-z1W5qGH zA^CY3nbaQ&O)E?cntK%b6Naer?7XbZ!tCOr?7Rs%*%Pyh z4Nw)eqypuOpc=9L)YcMx7d-(@X>9o>d{ca3W>J35)XdPzCZV!WYry?J&^%@`*M>6IVeqw}^5x3nyltP3s+R7-#2h zLV8j06bdNJEGbeOUxTZMx3#is>3vjFc$jjv=*H(vRed4PH8>+He{%Nt^un?UMVV7G z^NNdD<>SX^7Zx-+$+q|{l<6u@&zqi`UYwDYUN}+tLx<>=3hc)sRnJA1B#{< z2I&sqsjEERt@<`??FckNm47YDh@V|vYNsR=;}Trc&Q3)EstSHS)oMxJ`0NY@ZMxs4 zZu9Jp9c({uL6xcu)dY6zXsd05dibeu=@)o4@3PbF=9`#bpzRgvkJrSW)!r`66H%o* ze1_#;`;~Q@moH$=xX5=%9nW4}QJQGm9jG3aq@@ePTbQ4i^mUS2m%4K*B z%5_~W@7&Gy;%Zd9IK8mbgdzqR&p4Nl=^m8Rqg z+yYe)Lp~*AcBkbr5A9qzEqd6|iK0!2UxO-LA$v%#b9!2yo1K@Pn_X0l1pFJySG)4^ z$7gm*AD3N}nL9O;a-T>H>MdhK<>Zh))QpPM(F1f$6?~3rz}`ny04Hj0L3VNIy0dIU z3e$7Pr&Gl=y!vxal1(?GS{cxm@TD}M89FZ6rptuu?ED3PY{;KbuW?yl##CoRNnT<4 zG>R-?4nXDKQ#5O^{3)_Xw>$skd7%)Cq5M3TZeQn6h$Q6&7uYTw>-YyD?i>PSWiLZEx(_K6cpxj zh7|qFX`Eh~onJ%;w-2$Cw*~b=mxju7hT7GVo1L54Y5cfQ8va-c>O9OQOfQ*sH;-@NS52(xodfg~ndkJ0_iOWz;`9QQW`ZW1T zKd?OW61xUQpvMzYTAaz%ITY%FSH-8e_!g+vTJ`0$x*<9F(}Jtj<^HOe=4Fr3T%~#; zmCFFS1g}B37M0IN)r@N{v)vhmSFIgTH9xo;=#*X5D9z?ef;Wc`9&5Yx5UN2w2d;Vw zxs}K)E#ROorp=+)(0Is1&WsaDpcAXuZr#uVKixa4O(nZRqkF{_RxcW7iy4G(3je#m z%4=P=hkdJUGpQ&)Z$frX=KFY+bq=XCB<)dEJ}oOdBP+yZrYN(NDnl3WOPy^#!KN=r zFV5;TIdghOb|hcVDD{+;x2IH%Msq6CWFAdt z)a#$wuWJ5hsN&yux*pXi6%`j|7tjbUi$Q_oC)tkBk31bLt)sRBy=g^t2RT|obMR`w zxa^56T`t;1S=p1bCuN87a$EuOB#g_oJ#2`oL19z{?IWG0u_+a(VRz=a118_{>rrjm zq5`|vcA*;YiEy3lZD<@lXLI7IzdWMWqMuH&>t-_>N+WR+(=2@ut__%PLrLU zjH<;E^dz);KMkQL414+6sPK-N_VG{G*paz% zT6P)t1EJ8Z41*eyRBjK*OX}L8Ooyw7SD{VNTvP>oLIIkBC8&D-?6tO{ldiK3YJh6U z$7hZ!VV#9?87aMfC!NZ>?s}WP#U&J|#ju@%8l$6T*`A$`%2%Hx&2O+3{hyvh85#K{ zc}(M4%GcC1aBHT7yX)-C@u8_@+HA-ERdwJv@# zswta#3zuee6skE*Ks9Ae(6;FJH`}Rs1#OQ{BcDca$89!U*^2};ln>o*BbMPc74uM4 zP>8lho8DoE_EuEs3o~=m3nzy{2bn5O&0h3a^lel_-{(#{vYk++Uk_IY#`C<lKSMQAub|>jph|ZSs-DkAo1tZ>hu(RwZD0xhDAr%iBS$uXAt@hM zQZz1qdMNb666=RM-p>_~n_V0hokx-fDXc$EA65mk7}_GKvlt$E<<&?{`f}l|LR&)y_Wy!npAU1 zYVx>Uv+XIrjh0GBTCPPr$v!iNDyTpse`28t zWtRp|py@g3<1>GOHzfTRsFu#}Puc@@AKF+;HDUaoiizjkh zIW=s1-1aZ*CVz3`6UtVK3x8yo%N0+&;igG)#Tjrid_Z2 z60Zh+iRyrP9X$bE?eg7$YPHK;^gtjs!D)+fyY*>~L5m17g zQ7yYtR2kD9-|~j7crac)o4(yPxSNZweoy4gH|ggb-)g#dzua2CAmMKHeD%*g& zPz~)YR4uO_>i=qJ|3*)g|1~#-O?TN5{PhDng*W20oY%T^b3e54H{&(MB@vDV6;QqC z{&`L-KC%rdV{LsI-lC|ZVfa3 z9w3_tZM3h5(8jtHuT?!Qb6i1s#^g}t=eC04%)%nw9$)>19jS+0`uFi#-PLcvO~9*T zO;Byn`Q+EhF>9~Y^hr~-7DFXvh1s3-2v|^(H$8)g`wm~)49B7xx)7=pqlk=}niyA6 z^@G7lU)utU(+kqaaW8ZW6{$mIs5&$b)ri>lmO`P?t|5K?ZaZ3*KtLI)K|d0x!gy4R zvMs8Lk3lumKYV5zw)b1ROWsB`^yT|)fzRR9^LpRe1}ws#g1;JVjsBJVDzESNLBq<* zpCX`ps}G3K9R2o#otrOERrrR}J5X)UN70kfr%B%g{q{#&(L-)3Cc-rpJr7!b6RHZ2 zI%Ly_P)+e(cynErIuj5$`)50ppZ#Pr#=%uV6m5ZC`HLNy*HQ6*ejJ_vKOSEF82laO zDBVBjd+D(4;M>GE>PrINK`hM9n;3c?prKrWs-Pqmq2}&%R0XwgS|8Q+Y#R;-4-6*k zr?xn=?7}+XV9oYKwbrUn>`r(sh3Yp1=hO`cGu{HO>Sji5zPC`NJGq|KDX7LJH@%=! z{k>X16As#af)@^E#6vX`OW`VD7J3po_$V7+ zovsI7{VgJ1=`U_z8+f5B_XFn-Ml81-U?!{IKiPJ)ZTa~8;!YX7VV{>DNa)#ymX{K* z0sQB857}@*LoyQxqBu*9gW-b&}U(NP`|ykY=uR zV>^^bp-Q+FRly6J*al>yT3Wr24+m>~CSK>$XjJKXJO4n_aB%)LYi83OXk^Q~1+M(3 zkgiO}#VRTgs3L(5%o5g2b2I~0!&8r{L&{;or8Cv z+H^;s7!H5j2zd_uAL9s*bXM1Qf6B?E`M5ZLboEJ zrr@`eZNkq{Rb2fc(Pn%b{L`pZHNBS#g0^2SAbg5$mzGOZ9^hmZNvU{PB>^l<8HR1^~7sYR-&q4V0T;b>8L7b zgo^)8eoe_Iq|^EE9OYw5FFG zp>kA1+zr(n-%q?6R)N>z9EWOz2B8|cmc%Pv$fa+Fw$@4h1raLf4O9u&qG~`Hsut(a zfKKQOee9ysJ+@9b9-#{h2#>wMHfR8<1|*cLCSw{ZRmROx>`&!+zf)mqtzY6@1MYRH{vu#NL`@(XF`MT6`S ze-Em~`z@-E;L08d|ZnCN_;p_UhBPUOANf>4^{?S|QHo0B;;kMct& z;x#gdT>3hAjqLc$%mUtX4Gkrq?h-nnZP7_Zoyv;F7v+Rb0H{UBp=wZFG`JXDWOX#E zMYJE)k(xa*FTXG|6#9O!9cuTq8k&%uH@*{($ET09<(%ZSpi@qM2Jdj7d_YnhI%$-R z|70+${x}L;1yIWivvUj6C-8WkIen^nbm?e+Ve58fZ%~ic=!>Y@Rqde=L$LDA0 zqMZ34=`?dUquP}(rr4Rf3a{!?C|dpGliR$BIhlofF17udo?jBY;k)26+rHf>&EgH) zG`n4SL$_FWY|rDh1akFZcScsGdom17%P*XqSvWqFd%11E2vkezY*b65DXOJ%V60t> zBd9kK2!zY>JnUy>d4P>{vuSH zCmB_`j;J<6GZ!Cn@n2`y3RVU^43*!A>R|k{j+Fhc^@IxkgN~H_k9u-*j-BhgBHObM zQH@OXo#~r+E#Bvg?Ubdv9`{AHM)diU*8Eqgc1?`uvy$BWg5qiU{xc^xJGt*viziL9 zE8uZdODD6aTPMA1cY3M+-O26B#)4H#Zf0(N_LZ5Lo2T1k>rpMBM^SC%`%tCJO3&kS zfKaIZRW|*RfgWEPQgE$ z*#G@`9Z%2P%KP71p^wuuZH34zJCc28`B$FWu58B*wx83xBm{@=tIjXE(e`&fsxxLi zTs!p0vhU`dl{&ZG zn%+IU{9Z48Ibz}Z)dgq8#H^kjUl5MjUhmB0V_%MMu=-%a@NmrgxwAIk`q07aR`>6@ zBN8)h;yJHO{N~(kt551(+AzGtuNau@?ThlvN>yP~*&v({Q_p@B+}PheFg|>*pE4-f zI|%DZin@NAocPGu_5G?rN#Q)d<>2J-J$}mIWbfztp->_Tf=rR57{6+8k~cjj7?1L! zlq>oSuD>6bljxnp0FEJXJ-^N1c<*N1dDi8`hqw7HhbDXVSo;HEQKbkE_bY}bhu8Z% z`TdIDa#(V>pP$0-1%3s;U-NekOOC`f^kau7c@vqF?qsavSN@dXR}4=MzwhrHPV_N; z?1-fBL_cLjvbUa#XMYlfReH1z)7;rl8$`PZb+vqMf}e6xa`VtAULGBP=GRAYbP$fR(A zzjI`=_X0;WUo6f=xKJJaCa{tY39$k~ffBL$x8| zrw@;hUXSbQ#|=&N{z6EV)DP-EnvJHcQGfR{2{9ODA&MdMouh!%`0x(DA}u-Mo#Uo|$#8^Jw-qM{mht%%E$!@K>8%agt1TiNBv zgj^gS9_Y8cB00JUcCLx56Yk|#T#@W`=0+o#%+zwJMz&>oa(JHvuI}^u-VutU;aZqVINcj$~ zrj*EOC;L?yN#Rnz<#^Wh$u=9)I3nI_#gmWv8SI1bW&Tc5bZ=`%Ggug20j_3eg*W>Z znaN)LcD9UQw?(?O^J6C@c{c;yienPC;cN?NPo&Xle$|Ae$OY~F*ojHr?DnBhZz`pa z*R!K1CWjCEJ10_c2Zj+I46U~irxk`99UuJ&cb=b?p6GS!Xqz1Ncc;aBML11;&=hZF zjbr4!pK)5@q-11^Pq#;uP5CNLi`2SbaayD{<=``TRKNv0IC>9msK0n@Vzf~wQYqx6 z6B=l9)7N!4olteP;Jj~enk5GK&V=xper!&Xm&-(5SY4vG8mBgso_6iSX)`kg!xO@1 z`LVf4(YMa#n{j?zZesWbzalr8BXnnOa-?ZjKQ@n1?CPiHC3!xXG%@vq-u3Ec$4;fh zhi~*-<|libVJg|K_Bu3C`zKgS9Gg4ylcVcl7x;^ZCwjjVvSZH{iX_MT3k#CGnem|z zy|*0;uk>3^N%nTb)L8~DKR(ht!CyG#8gB$0)@+CT%Jlf~d_Scy+1mvWRuXAHb=xw1LV_r#WsZ4~>r&;f9+1qw1XF-##$L+l18= zF+41*`m9gYz$CJ{`r>Rcm1E;0SM~O*h9`wz@>8ZIhY$G`(~=`eNq*Hd7B*Rw%hM!8 zUm`eElNdQZ*19uLNF)WP_-{tR|o*aD@HZVxr zjLprWut#OIKki!b=wAt45rjIj`E2N>n$Yp*^A@?k_{v^&3D^wv816~R5H9yqu1=0_ z#oL%c>^2+PM(CQL&_T5CvLN&jAsgGFUv+2&A)Bs)#x+Q{oY2@H)MbDwS0i7k2_p$aWrc%PZ(1n_DxY4|8{$`$Cwb=%shOf|F6J|ny^kPTKAaKk zyi-^)n)_h3!&Cj1*CvNo`zieX(yzES*-IK$om#8mTAcQ2$WI>>AAZJ9xh^?UXSl!c zx+E`wvp^FQ6I?;qOxGuSe}O4ER|KkRFrs=h>279(zmpWV!Zby!p#1poMn7d%vR8+5 zM4P}KR>?S(Ya6)GZ+Szq_clzqg8L$`-o>F%3hr2ccW%5l1E&rJmxl1`e#;xVj~Zz^ z!OGOp<6PMAW@|zW&eq1YDcWO{7Ejvjgl;Fqf*g_P zeLzV0?cTiVl2C{OwbQSN_g=^8h@_nyTCK;}R?`zMog@5|o06l;VI%#;*Cy&XzbV=4 zN=MXsj`>;fy1BVIIlR=b;P;3A&YQUmrrI*>aX$jrmDEfJ7q?kByOZdNw-1*V#A%}p zywr|jaM|`&;>N2Mv%4-Ma2dS{>eOZMMqJOp=~}l5ryg)4$*IvJ%}>2G$(u^KN^+d8 zGT!4jJ3*D##(O{F7!fz+X=Ck~&r!uy`)Qm#OM=@&oSJK|+PyEg$3<`&dPTT1iL)K6 z#HpM1O7jkm&B{V!GQ-(^%X!IOw@)s2&WF%X2oYzcR;s#xz4e! zxv1Wc(?0Ob?)r>3jx$QlBV|`6LUHwiGI=wk)(yd@0SIc88Zoh%?rXQ}{7IrGjTCm`0bCG%P-PcDB+koc4K+%cxjS>gD|>684bs-#H4BtQ23r0A+i%xka(KO>}J3NEkF0h1YC zKkec~?@mH?h$`8PFX7a5I}CMm?5f~sO6PKzqxGu#! zljCSLOG;l>;^HsIqJ0e4HE>$&pEyTbHYC(7;hVVr;$ey2a6)c{vX+4%dW& z8KVp4vCyRas%+w7Xo5a;8x zifz7^ajDiZ2yN!rGVLJTgNrAwfgV!5-8gl-p1=FDgcv5m7NT+OhdY<3;L#;|qvC>x z?e&B@+rn8@U*QG>#p#}->&^B=Y!KXml;E_Axhy`G5OWJ(Dz({Y?{RZ$Fa9fW<7^y- ze1KzXyCpsJ)|#bB+*3IAjf*?;w(5mI<LxXU%(C5gKDJ7d_VT-q{yZ7{nV$EygTRD9I+Ji_I$sJxcYbbv1^ke zeed#9k?D8&3)d!j2kxrAZtmu~6mRT&*@JAdb9IA*`d(Z@&>xQNXrl$X-`h1XF?uPX z^YoUIx0sNYA!h{xwc9y6Y;7y-6^XdP@sUd_f_K|09OTlL$xR>5jx)EkUh9R`4O3z1 z&IN@G zmr6eVNr<_pI-$<>$+$lX*@zodldr+Op%6Fqu9Q@qjs=dULGj*wI1NO|-_4QsIZiu} zCogUV&s*YGJ2lV0dCQRLPW?xIy7w;Yz=1W0H3jKr7=IQ+YlO!*#}S zHVlsUKE@>l73jIR)qQ@|Cf*aduX;GN*|y?rFXc|Wzq%)KQ*d@Tf+XcgCZYy27O>k zxd&h5;<#}g5g*z6pkK8)$(!+zU2-hPoP-#R_CEW7#nNS&J-S#rSHwqdSmsx~l;o`k zo=pgaBEU@5Aa-n@s>pIp_R6g4gB4k;-f#{xIf#P z80q||zwoa~k$WEXtNxng{rsrCig0hp`oHKgKlPQQsQ;J})57TMgf0l$ddlO~_g?9D z#CxM~7tkZt4v%ORxCETN#BRq8$Jx!=W|g~3Gi_Qj8@Tg=xHfmkM=No?{J8YQ=q_e*uYy8z1In8{J8nv7#|IGBuj4vNGH~64rfShwtnnAVk>s^{%B~*{flK1Ot8unBO7i4W ze(Lt5$WKrC3%4gl2RzMj8H~(Bgf0w5W}iYq>sa*BbJnsPg2v1tbdjINRJ>0}DOf~> zT&338yH0y^o{bwr9FLUg@zG5<#vwn^tMiP#BGM+d(vWBT)VGtoM}WFg@!kq=-i%qV zf#4nZ=v{J#`AtE za^Lg*Lgb_8{i+>F(Hk~~LKFR6I})S&2n|rk>%OV_yx>_OIs=#Nr%g+YjQfipTb1N3 z{EHof;QhSFr+@Jm0-L{3eJ!XgkM{=Q5`y;X7WX<_XB-C{x9}TrT5JqEPeG9vYX+2q z`<~7AlEyAC;r;oSY&&=kPi$|50{iAn?z`mO+lM}z>SqNZThfP z{%Yri+{7)wjjl=gcbwf~ic5OM_Qj@LiMygEWy4pid!7DdLJY?3KC)HdM%Esh? z)8PHXPm{fq-r#RNNa*P~B{K01zv|PZ=!d|I{9T`NVr}o0WW&3ZhhL_?lASI1u-#&xm)`!h> z)Z4nP)s4f=gf1fmCs|s2_zQpM7s+17cdCb8o99ZLb~ZylG$96Khp=*dLd?50Q#&}` zE5`*>>!)uDqK4W`M4j)$lcTsg?z4Je;UCMHtTb`u+ z9cS~YhG8Gsl)V z*f$b#!>{XVF!Dk<1}Q! zThHD}`|RSim$h-Yakg4Yc@ftYXM1!Ir!s^4U~kah?O54-H{w*Lb(>rqZwc_x#$g;6 zT|Nmr{~P;g2)~>yj2ldzV9$9waCYIQ8!jW?`c=OsMSuO4D*d$Id)3`f@BCfACVDp! zQeU`4vm-a+DErsMXp`@BkE92hVT7&-*kgpa;W^x^?)SQqDA_ndEF(f65}Fi*`v1Tp z3_>jrFb6>>n^6BCw5ld_h!7_&c?bO%+}`|}7+LCe+Jj;UV)O+%WaX`>}>sZcM2Av&KXp za$iH}ydb%D_eR`MoV}(T^GnU9V2Eltv~MzZ{?%@7yIHTtxfRWY;BDt@ zA5J~&QkwK6u2VRb!s5sXj4EK~6vTU{{Z?Ip)?x{6Y>-fE@h#jyoIQlv|87$2hm*Xq zzuR3&MI2j?}0uD+3GpDx5*KpDIv z&MoGLbxf7gw5S_)^Q%q{#p!t9dW5?JcP5T4ru!?LHV2)1Fdh9Oe*T#+aMfVGr7wNhvU63oek@%5IOB=6Wf?X zbB?wh;)E!OkGyxZSt#1Lp&fysLEccDj!o-sz}ao4YsO11B`ar7Ld-FCj%gQ*YB0`@ zjt-6+a9#afeBS!ZF=pZM?A-4m95F1c(qnBSxW80OpT#O;&^_-*oIMkDE$nz4wFlS2 zD+p;dvH(_anB#OmK|6}$Bm0jt3!5<%@r_Is8a<;iCHlLDB}OJRHmS{t`Jk~`h#P0Qw5C$ zok0YTE_Hd7E(BuD0;Z?rQAf*37`O1T}*;S+n@s z$tK|X*@9OROtjVQA((B0BNA$Aej*44J#EsXCR+(XJ1X9*1a(UlR1|5^)5M;|T3FMQ zRc_+WVi)yFGz*2c_Tqdpi$T#wy*VswFoWP=8+?r5KpQ+naEuM|70S?MHn@`DP#gS( zpv%@TxhCin9BX!UW<&|O8qPmgx#G?S5*lvv?J;uI2ZBkKSZ1`pt`8& zM1q(4i$CraLqMA;sLX3UkU6e)(Q=&Y$!i2JvXz}Q$ljB1i_O717N?tW@;@E#J%ZEW zWAEsG!RavMW{kU+3kTc7gpYE0{JLt09Y*`k&(k=252t&W=ujKSeGV6qLC)Fln%s!9 zms##;q8k*a&x^h8!>TWIdbqm=*Ey(J&o__abmKy+xR?CWIa#hzx4#wo6T@co**a5~rQD1MH!w_my_v`VoTmtdYEMJXosLfZ2& z)ZR!id(kd@CI8&u-O(wjrb_Wg^G6gtRJW;Y%+0{zOHFD&@C5#j=Io$J?D6RRxFi#& zi~m=bnb`g$=$Xb&B0+F_6uBYIEQChhN;6f8?L5}DEcm=Dk~P+(4j^{zShEm~-h8<( z2#W`BK72{=QXA}hg-+LiK1eXl2J58j8X)RTAZYLY^cLn4Ie+n?UNHnT3hX1+edBR< z?)VNEt8OSxbHtc%!+wj4V{X_JpEwshCq!Cjn5x0FJR`$iM{K{I%rL1#Xz>G?x)0&c z#}cD^338QCu=506PJ`fdf-b>xf6)39YtjxS=o0t@UA7Mh4zVS4$f}`*1i1>UicJJv zf@8943L8bxm2eM1SMDc&&@(30WSdUVwRa=ILAKlmlWR&CNzheM`3L=yV3HrlJHG96 z>>(YTXpx6<%)*Nqkq@C4n7C2lt~1Dfl?S3oQNN585kF*McDJwFF&) zmk4tGQ?_IBbvg&ZRDzD)N07^#5`6ndf?frG6h_dc{VPFN?lDtp=xBnj-1`W+HtZqD zbyek_U09R$N`fx!OEuIxrpVqT^7bvyuGivt>J|8iDKg}#mqwsE} z)#qLto?)lp^yJLh#be>Ur6zSOX}ZH_s)+V05UkCHc-e#;BG%U1jjo~ zeEZoaq#g%f`1D@DsUGf27>&a?9qAn69KA!YwsE{)kDHBC>Gm4)jEl2>q3{DvPmi>3 zChs-Qu&t_V(#P@u`Z!jF2E!jch#R0cKq7svF;yAtis{#AH}1+{O+81jpAAOKwAlhW zl%PxC|3N<>=+d52UXvh;pv$(3;1FBFZ-3B!Gj&b`<=#cmCHRD(E3D(SH6;`gbQQ1t zgNCoG$u^Xr%Qm0jAY1Oo1YH|CTwjxRDnUyl&tGpAX0t9D%&J~(>=5rFoUZQ-J|Bxz^PCIIRI5*7)dSj%|JLmnhNUa={-h z+(bzIV1se}cok=_Ch51vdq>@58^x9R*7(T4o6N#I`nVdZN?7c?RecDj99##-#Czx7 zT>Z`zZ$x{^w}gZ546~?l3vhZgv~C}6SdHs7*ShhD%Pne$qr&F93qI&(AM&QN#)Zu3uKgwU~bUG@2H9tys4L^!6 z<3}&FEJ$!IMiJNX(~O@Ae(LkHgde?@1i!7S!29`8`UjjYMfLhKtp{Hb#9CFpN1T5| zT^Cr%k6QSci}*8D{3;h;Th*W^`BD5+F8x(Al#e-hkwzPAL*O?==Eo+ z__u;stMYI26Xj>8<5KY|e$>1VoZp4&B^CdOAEo;^_$O^_fZqZ57mYD1i^HdtDc{#Y zk-wRZk1YYiXJO6gSkK2*q`932LiQM}Dc| zPA*=mdFkSOZB@FiEpFE+s*WIoX4B9NWQ5svw7R5YIUn6wJ96 zylSf|fx91FH|5wAV|2}C6Maad)#@c{L@aKLu2qSIepFXcbtBJY6ibR`7gA` z@o${|==8AutuGZ6rFp90Xs1n_#yV}|v^}cyot-8)u789~`7d;QsPm&xox7K!dP&uw z%bcbiPe4<6g-alXnAo3~NAOo#tWIipAx3}6u8s;E01pYQkr{iAY9ut>50q~iCu4EMTtsR~|#3f<>;Z9Nvg%B6e4#n)El zUkz7-*F{dS1+8}(o^=_dVYBVZaO)l<3vF^(s*StZd8vXgJ19ux4G!r zD)hQb{)UT}D*JY)Z#w>;sItBt37OSP!i|Cp(R;4Y9jM0keOLIOsT%Qtilo>t(>+-^^z)hGQX6r9jXG_JAa1L&M5zd&f%9T>MG+@UjNGE zQD`!%hWB&v{mL8|hAQE37a`TX$S4<|=D1W1Nk^4_oYM@a<54wm0;-o(%Q*)Pu6$@C z{2Y}3LS?t;H!rCQoa?+){#NIu^0%Q4(YsMqbdS>|s9v>IJzeH_ZB@R9EibDM{DZ2+ zkCQ<96sm)I1FAe5_3OV;C3%5g8mX62HRN?vBlf3O1KAA#;;LT z{Jrx(p(@~4R4=K5zdK%+Op5nVWJ|WdFwkRB%66pj2Li zqG25DxKs@s;=ELTsPlg)^(*5DBBUcxwK&Tq{C{1`YE`6#Q-BvLcD%N#2PKY6)!-+{(FR6l?_@(?WI{t6e zEe@p?Y@Do?? zr>?--DzwMN?{)FDRr$Ym@%vo7RONqzHbEo7A)o-`sUFoqm9d`2_n%Z{9ObxF7lIQ| zopL9mif@N1e+N{rf2T@Ub_NNRwu{RkRYBcQHK;qPggsEToIhjVfb0oz5>rH3Ijbs<6`erOq!yHARm( z{{*UX)}qI1{k=>;6>ULP(5p`0Kvm#ds50zy{sUAE{1DYks{9|J%Kr(fU7&xqNq)bJ z{|?nb_cN+{fcg|#b_{{01XNKARQGLdP~B~Ga=bIjf1&RDibaQ`>d_^r3cMUu{&A=p zl7Xt+DX31sa#ZPWM0Lb3LisOLSoMJsX5(HBu|i}z5q@KaO;edqk|s49w3nl!3X zoyy1HTc9VQBn`DgH3A(`jo2BeUVmuDA3zDtB!PNx7ODczcK#ex1;sm`fa>)>(K=?| zjqb6rm&^9=RLw|o>7;5-vh%f7>H0V>Rl4&~^}E00Qt<)xwa{%K00UiuKT{Pvn0WPn zm`f+sOkaX3J_Xfyq@k>)&^S~tsrUp`>9U+os_zckNdV3COjH?fKvnRqs9Jg(s#k4Q zL+)_#zSBEhI;ob}{fkm?y?jpI)_E>%OGMpf}Mj!V_E=bW#tO8-1u zJ>KNfZFc@;RPkk7TwtryzoM#O8>-#<9;#PuRmL5TOVxl6P*wDy<5F$fFC5>CD&Ln* zze0JHgD zhWeU#r|Q9RcvalQaj6Py>a@AjmZ-{!MfLi3sx{V{bkX(%PIVdEqN=Dps+Uv+b`Uq6 zZVopO-Wu(JRXcm5{1@uWFSVzi(*dZm4V0SP$Jyj6b(F)SU9vGwQ&BbNa_7@g4QZD1 zlThW)bw1ze6jaS9aekUp{p)$+Gn_ArVUV@^X94&xG}k4VhpON^1)a(pyxPA2)%aIB zf1lI)QN2m>f%Cgiy`;+jvC~gn{HHNYvLe0!sAqpi)#LA-9&~yb)k~@d{O0s`R1JyI zFQ+Q60bZ*AN2n&?IOm(78iD3cPbhN<;!qXb3RT87PEU35?VRu6{OPC~+8I@WU0r;< zQ9UO!z{V>PNE^>iUE+Pe0XVV=Y?|2rf0`gJ4Z+fNU*El{4Z3}-GRR>n0 zDrXIh{X{T$^Q?OE_dM<4 zRRemUdi|NIK|P5N-ds)$0{oeR%b1L+;6Bb@fU4sD&JRLWz+k6CP^BM+>Q!6y0bQo! zwN?2iD8DW;6BR(STtcaQw)0Z?NzO~aesp9j9@1Q_F0rg;t(;`&7 z7}ZO9n(2MJdkgVyho#!R_cQzgF`U9YhYh1>)E}>Knc*c3D{IkwWm2ZRd zQdPXsc_~Xiv=!BQeh=0C!sn>&JipWbzDgMm095c#P7k4aNmaqm&ev9@{}rx{7S=ZY zPgMV8xC*M{3aG8(QOBifNImDJ+7Kr?|DS5vf12@sBOfEr|MS@Oq?_x>|F_Eg|KC)o zDd|qbwT612@;zNgr1FW*OXYhx?Jch76$Mnlxh|rQBFw(E+)-$4^}}i@3=npzIM%AE6coi_&CCqj4 zf2Jxp-=!~b>7?R?sMhdo$NyDr{r@Hbx&Lhe|CjOFoqGLi%j^iuAzmYKlhd1B`r4}V z=T5k;vx{7OZPnD=x(d6@^ivM@N!o&RkoA2-hBXO;(_&QXJse&K%dG)yUn?j~e=b)1|0h zf2Q@c{#FFhfA$?7ThL14wVEGu>HbU=zskkeRyF8JeiZ+di?6L(J3+*e@9=1dj(mrQ zm8;!W`@1_@BJx^GN4~>zx@A7Dg9Qh89{f<=a@9t>1 z$ZN$M`3{e6K8}2c=g4<>j(ms5-sm6s4v)^q+TZ2j@kn=_N4~>z)q^d2NHsUEj#e|JY*UXK|^zQc3mJ3L3e!*k?2Ji%dbyYDCOlm5<#Ch3d401#eCw5GN4(hm^jA&8j*%9o?X{7?;jk&ZHgbvC z+A(sp+14R4DBRby>Xr$EA)fZm+|!_1scfIR~H1V)%1X95Oy-2poU zb_q;29pVAA699AL0l8+UKtc~d?*u@;nUet6Bd||kis{hjk*VEbj$~;os~w4SNG-n3UcC{x4&U zhd`O}_~*V&Rx%(r2{6;F6KHWRATAkjoykrHY!TQdFw3+&7f{*3sk@1a=ABY&x6=n0-EA?sD0WX`a0`12DI$Z+TYNlTjxg`8ovt9Cv=`aR))y$M^Gdm@(nJy{F>t>GR4YOOa z-SkLB-Zb+hZ<)Q4w@sf*k#|f5Vh&zLC5JDilK0Gj%K*#L04py8>@YFJ^fb zAZ8MvVK(5fNy!GR71$u~yYVIgvL*v^Cq)KD!V&Y#q{wK~A_o#TnIv^g_GFT55!faW zH7#=hrMZ9^Ie_|Rt3dlaK&M=QXQt-@b_nbeXka?z0cPg|=H>w!nwtF(kSTzsreX@qR68WscMOiD3et-uC>*2XIVWK9L+mH^tAbpkD>0pg|tPBGb20b2yN z3A8mWrvXY!0W+onPBU8t+D`{`Dg|^f(@Oz61a=9WZaPc{%)SyZcRHYx*(s246`=Q( zfV0e;D*<~1_6c+`J+1;QxEiqdD!@5ruR#A9fFV}{x|xcr0S5&R3&fiNGXTr30j!(> z=wS{Cj41=8T?0ro%dY{%lmi-;0eYL1GQe7a4Fbu=D+grF1mu$N6X89bzn416%ZvtFuQf>mo+zi+tkY>D_0c!kZ!VX z0koJ4*d~x+TFwP*5tuO-kZHCGl->&HbSq$@nSLvv{cV6<0@uE3n`Wz>qs4gNEpzud0649g}k0%PEUi zPdN0;x~wI)^}l5JpvhCWL>A56wI}0N*_lYSQ<%K$bD%ruP*pv3|}i2+<^HVJGIXuAL~ z%S>4SD6IgzBXFZ>Qvqnd5HPC(Fvn~c*dfquA>d{+b0J{%BEV+?b4`~;fP}jN^A`bb zGrI-$2=u)hFwe}p8?az8;DCT{`YZ7f@kF z+zS}91h7V6kqIvW#8d(@mjD)T_|2v5AF7-bnZ%rjL%$vS z8=q_4YrIN|&AN|zax1B)(yS9`aX%pLKEVAZ`#!)Hfo%dyP0RZMr4ImR+z)ujY!zs~ z6wv7bz;ZMF0l*G{T>>jihoyko4+7>c1*|kX1ri=xfZRs_o6I_a7LNkrRsvoy*((8C1hxrmHZ30ols*QS z@hISBvsIw|=Jmzba)&vdlg{rKz`5HjX(}0Fg0d|>`rvPgOHVAxVyr%(KYXP}W19qEr0xi}7;?@E_G1+SYTLiWV zd}dm%1C%}kn6VD=a1Y0O8FeFFPUj}3qY&jA*10DN!u3iN*-FyuMF0aNiD;Gn=^fuGEP=K;$$0#-f` zIAjh9jM>DV8kYGN#w}n*eJC zGB*K!H>(7)UH~-xi|(oFm~ns6J=Kel%_4Q`n8q(awuqFxK&GhK^a7bmHv`(f2&iwS zya;Ij65t&H&$QVL*dZ`$GoXRlE-?FLK)06w4b9A#00~E-z|V9X5JP+|Gxqb2sAZ)wgL_cEZqudZuSc-dj&A+uYi`O@~?m~uL7d408TI? zUID~x1FR8wq}z+ z=^KEyuLDjqQ(gzO-wt?3po3}i24IK4tTzCso9zO#-vo5q4(McNZU-d11^7(hEYsyp zz#f75ZvwiQ-2w~V2K0RkaE_Vx7NGw-fCB>EOrN&_2L+bC4Tv}U1(v-F81)XIhpBuA zFy=i#^j$!r8SyS4W(Q!6KyMR%53p7s^F2VaStXFQ6VP-AppQx40ccSL*er0qX|xlt zMWAFSps(2^Q2IWgZ55!OnNkI4{{i3~fdQt?`+yw+v)%^`GTQ}a?*erD05HVN`~Z;f zA>cECVW!J2z#f75y8t81Zh-|K0s4LjxY*455YYc)zyX0#rq4%!g91xG0$gJD3oP3W z81*qA#Z-O_81pwkbT{BqGh#O&<`cjgfix5T8(^(K=HCF9n^gi?p8}eG0!TOMp8#5X z2G}f+VH$l3*dkE!DIn8q5-9x~(DpOHL^I_xK>IHM?+9d@HlG7_2+aB%FxhMun7s$k z?F&GznfV1EVK3k_fqc_t4`7eL{5^mvX1BnCF9Ch`0*cJMy@38-0S*Y1m_A8A24z?gl2=+}U&%!sc6F@FcF5tw1Z`v7YNGWP+>%qoGbZvajI z4wz}u{|;#JEnu_2b*9lbfGq+g-vDNrO#-F+0d2np+-RnJ3uylx;2nWErpd0B}%X=>dQ-`vsQ$1Q_)rpu$xC2pDq^5d8_T$c*?25OWByMqsfC9|Wuw$UF$R z*Q^rA`Wevl5TMee9|E-a1+ZD*e$(h@z!rg$p8-qFCV|pl0d0Q)JY=T)!lU^zvsJR( zwD}cz*i4tKFxw@Mm=1@Lm1d^oQL|I>nCbEx1?~Brg6985L95JeK==vM<9B4WnJ0PD z?3JvU->1$c;iu+T@cZfc`}w`r3(hn z6|F;G>(;r7g*L1FzRT)PE&a_V9YUqXhXpJW<*0k%&~wq0=rE37{FSA z%wqr_nNae&XvCV|q%fVPbQUzjP40PULq z-VxYq+B6325SY~%@RivvF#C8ww2V%s(Em-|QAx&X}{{Q}Ec07f+j95R*70b^PMqAdWwm=P@iF|mL( z0*6hwC9C2$lOp-utU@B8y5^|ZI-?`ux@Md-QrA2qty9-DKB3NNaP|qLj+#x9dZy)x zNPRN}G3{GX^gAa~v}fAH0d@$?iUTw-+XZH~26Sr$XlQ1(BIhw?r{q}Er8RP#nImar zc1s$Y9w#A9%sk2QX0N2F>C*;jW-27j&3;J>GvH*TrKyy}nnRKk%!pHv6U}l-oC%+b zv@$7@)@GIDB;&P3+L(07$!4A86w|03a;nLev^AR~?M%zlkkiZ*Nqe(Z(!sQ8k90KC zC8wM1k~2()4oD|6Q*x%+DLKn@>4R0`kaAuHx-h2 zvtN>626RGtm`X`cb4ZeCMx2TCGRr0Z4|{I`Ud7eEduQ+L9UKxgAsYzpAs*bF;BJB7 z!Gn7O6e||=!HT;CDaDIJp-`+qad&qsa_)O(P4;d`X#2kBf1U3;*U80?HS?@zxz3uk z*OU-bAs8j4F^y8P9)@)AMRuq2L3WpsFdqoq{UA6%K{;{rh2Rhcy?r65AbTk2=MOo zjfz5GEdoJPsa*tu#Kj=^iGt>0Dhk0C3fdNhpoOfbphIy8(iMXsOu~vm;9dfP0~E9t zx8e{SqM&zi2-?aX3i_3VAZG~(+Dk+UWNimIOe0*fmW0t!`qStnCuww+yrp1tk)brY z%6S^y#J4nz?lOi(gj}c5LyDAv(NiYT=q2}Q^p-MZVf2xiH2TVO8vUe7IT-zA0gVCj zp2k3_T^`0DSwUm4m@2>+B8_Q8%6b}6lB6Pxp%Ml|+$%Go6_JeL;#P?XrJ#2u2u8>r z3i?%HLMuZsN+K#lkf$mHXDApWS*t*Bj)DKU7T9R}P>)I{64GvV?{J6gJK$G=1oF$%Y^ZJp_ zH7&H4-A$bnn^zT-C-t3gP+%Iqd3`hIRAy7e<~^a#$1N$Y=g>}FiuzCsM@Q1(K4C8tVt4jzu8LlXPUZeZzL$mY#g9Sn`NdrLZrdqOg{kn%y@nCk-=BM?YljzAV4SO_k z6#8-M7Pf4zHOo1z*;*vTq-W1?&GqJIbDam7Qrv55;#oma&tWEKvIf%Y6kU4v>=o9! zL)#qqOob-SpvBZ{0aCjLvSgc~>Zt-;4B?8_6e9C)#wTp51u3hSI;TzXu!$bxpZLa> zD_!XEk<#$SyrT8y&=t;RXKQzSwnDEhQ(9I{s|CJpHNq*1&sVs{7MwhyEEpg2NkZB0 zD5=C#d_uhR9R7d*+jF3bCE2wpJVXIUq0O;KL=u-Y^2k|r{x67yGYJVu3osg#UfYUg#pbaimf!(;j9rer+jtDq)va!Rda{INhGB}=1Z z^k4f(0nD_zEK&=glu}Hm6uDcloRXziG9K?zQOPnW84tXwrer+7oU8XdX4N>X#yG>A z2W6d5TM&7kIrD)V?#}SAEdJRbWDf8EO&({)zbs0TsqL*~UP_i4vVlsLRmphHYowB8 zQ!*Y7I~6keon6V$H9L&}{L8^JyBQmv^D>nZ{N+?K9xFOSli(OT$e21FuEb*u`IkrO zdEk1nlI2x0o@%>9$?_=~I(?^Klq|oJMcN?biJkl_03id(1db`0w^HP1ZH_A$&uFJ! z7H~qze3hOTWG9u(Psy@EmPpC`l`I=%II&pI{{SV-4j~VUW+Ve4V_D_^hjGonvPv%} zu7AZf>qI%2%-&p}gVL)AlM&1f!j-HtOy+bRz^^{B?o_cLd8fOfA-k!{vzwB!UEfkN9z4&;6a~GNEJDeOL6!!xtT2065Iz-) zgOn(DmVZwuGOJ4fS0&>K_0%f~+?1@3l9hrijgs|MveJ;HS2CVvPq$^jKwR^$zmk<@ z`Ufi^kGE&Q<$!UN{vf4T9ggC0ndybs-bB zN&GEQvU<1NoEm~&&|_AvhQI}8BVe3!w?VmW z3>i;oWKRC5WKD4WN#)E&C2I;9BT=2@&yN8xV$A@*IKV90q7<9snmIz*RwWC?^(I6H zvDb2q+1di&Q%3wkqSJPz*AmzLA!Fo?4-16hx;lF;{QXQlmVYZySP6G3$E_iIquT5) zC2Ip217<3BD_L7yGtx}a9wlpsYet%~y-L;|*DNw7a-WiQz_mAp^n|~5W=g^VzND)C z9Z<4HtWo&uzE%dTvgDFy6D^j_oo85Pm?G&f{h_mtfTyyp0Wn}LSO?aF4d6$B@BC;- z`sYUL%ma9;+fuL$EC(yVO283(JeU9`f@m-aOa@Z`kH7piDVo3$T>J)(f#ZO~{7G;M z{0>foGk~KyNAW(OFX$)NXIX;lkHY0>Fa~@N#)5HRJeU9`f@m-aOa@cHG%y_qm;q*j zSzr&+UlV36=`!2m8QBPzjX@L86f^_PK`3YeT7odp3bY1oz;Jl+9T)*df>B^B7zf6K z31A|a45k218K!~hKmex;Joz>!&O%Kz$Fe^1cw%G;I0;UH-@$2c2Alu!q059pX(2^lC6D~c04Rl8&dxNyNP6s&GO$j&w=Y)Gb;1YB;0OFc0N|;d?Ld1F4tQ*58^F^#2b9?YLCEd{6G zz7zuHF~*C)4`41>0A_=3pgU*_t}!RC!@*5(2OI;3!9lPOYzI5QCa@W70W-lI@B^3& z=7AdUj3-#<2At|~YR9QuR*((6OM-wwcMt)3fS#Z?4-W4G`hsxK1#rH{>0L802W`9x zOh3TG!<*usr;fXWw7>+aL&h`Q%K{#mo&+QV$w3OhY2kI`*d;2Oc0J z@Z{GaY`Dk-GJ`DOF|zX>IthO3qc*4u>Vd70Z3DZ(UT_cf{R+4W27rNJFc<k3@`3!I0LTrRqXLG479awVoC$Ll*pG&P z0PF#q!B(&hYzL3Q6Yvx~1J40JEOrPS2ETG%cLW>-zk%AI4yX%m!SmbT4!8^WnZ5IX zhkf%yoBTxKVz3k}1Ixh*uoA2SoZ!ZQwO~G20A>SzD{(U5Hx?ti;=gX7JK*d$9C*O< zjKCAvKqlY?_@T<|AP2|=asz%eHUr>CW#^;a^L*JkfalZl^xbvHsj@K3f%2dNs0et{ zFistg)IN|o1CDt%aVFplEFd51!d*0-d*D8J1fGDW;2F3Ak1v5>=p99*kASt1uLC?S zd>M#=J->X|1J}oKeIFbJTfus;f$e`KF6M)Upg0sufRZ2&$P4m;{Gb5v20p+S_<;bx zqx0E}`SpYE0e?~M32Y!U;MXPGfHSZHe%|60cn#h(!+(##J;1LJZh^TRtOTpUIps^| zzpsNIz-GXC^;*Cu3qDD3;yw{XgN?|if-qac-!RY>(T)H;Ku^#M^ac$5)jM zk0>2J3h@Id?*PB7@)H;h#sYpMrv|{+b)1TTT!7zZx(wPN(fpcZKQIi81j#^hkP@T< zX~06T2rL0h!7{*aGWzpT#~Udv1V+KLD6kgS{Pgc(kRA86z%5+g26sSvP#viZ27E$# zjg;}Jh^O?QM9Oj@W&D`R14NV`h~!5dd0=c12nMr3e)!oDW+#5Aml`4NCc81VX1&OxQ&4CfD4J7l4@V#NrRh#Qf7t4vkF&IQUk7@qy^~!S54f( zDa7XpI0}9P!@+2<98>`v5ZBB|Xco|2_N=hvPLc{ycLi=zVxA>`WPSw1*b=U4EQiUj zd+j!+Z+ehhRP^0YVXj7N9<;1uBAIFc%?np<+9T0kgprFb!}WfolZ4 z0ghpp*()ts-3B5)gTP=g1Vl>pS(Yr3qj0%F<>n%Umj`e?U>=wc`1HI3Yyv-lq+mWu z;4}Q@6ZjCoFVzkO!$2R<7xV*sjkjkJYb-~SM6v|>z+E|*^oM>_#B~)=8B_us2Wo+upa!T8*t66DOe}jF z_Bs)uJ7@^%fx4i+G8@3e`#Gl;pfzX(FrY*_(SnK`VH$x{h(Kdy@;VIHbjWKu<_KiC zp*}|=+EJ$^plR5%d!!q7m7Rgsm%>Y5y&bl3F3)%p~13G33jC)3u*K};i z=&9p9uc;STPQT*nHHcKo-IQshmdZT=JN398G1W#^(nF5RMr4d!H0&MSJL>g;8+Q7U z)A8T;APV#Y91)nEjMxys`Zxe2hm0c!0~`n#AhVaI;f7{P=&?w~C^-|tfE@iciUod0 zIt_y*J!Bv(0(!{oV;$g-Gy)h7SaFQpV6m{0(d~D@C_WBhjz!1_)1Lm01fu~Hs7Dgz zZ^V8YEF5Dy5%(NB#{x!%*-nSdi3zwK51avuj@MHGBRUyO0?}ZKx=t`hn9a)or(^TL zTrdMLpdVl|LUX`uFbm8Cv@;^a$TMr{hS$t$<{s~tf+b)vSOgY=1;A*U^gGhXP9xjt zm=u3`1Q)=0a1NXWXTWJ` zzQdA5(*A65#V*U4J1m|RE`kQ-h;!gUT{c>56755Rr={KDd?c^ml= z_h~Tl`Ym_^UV|5)58yk6S1?}!zDxK3^F4S6a=;z^;AA)npkE#!JxB+fK_XxR zPT&i4*|yq*^9O#w7x;iez#9|hL2r!HhE5m`f*GJ5QI&j>e!jDGRjFqr`D+RH)67*oh8 z6qTveOcw06WXQ<`Ia)O{+$%NOH`G+Mr3t#!L@-+^Rl`@u=onGrOq0T{~Zn`>L z_rNvlM+E2&IHe8*0f5gQ=p%!)j*=cvfM6gP0mgx`U?_+JLqLBp01N_sCF?IpCPj=x zKVT%6_w_9eCK71gC>8Y9CsIom z6&WBs{SFKV!vH;VOamPg>Ny5v=*E|j_#!bH?)7|Wk69OP#wgV!>th=y8F9=P;P@_>q>kMjC3-B zTAX1{1H-krr*O>g{(5p|!#2L?je~p^m4M4Il)}eQm$tx(-B`99KB_RE(Fy5H+AOkqJxA*#+FV(rD4=*BlF^V8egCE zPyHHVu4GS@mc8G|jistV)#bzm(prY`AWw*&W^z)zZq5qUc z7nldZA;3s7LJWv0JPm#aC&6)W44eR`z*#`MKLGV8r<+TF^2==87r_OEpP*TNkG3`K?>mb!ho{WfR#HP%$x8p@;d%wQ_BK@C&&mg z01w~}s7xr&3~V5il6xtW_Pl09vMHGnL2uj_1O-5TkPqYlDw2^-xp0#cquYj)j~}kxh;jeF!jG81<2Z zk+IE-HI>bYO{p{ZRueL^mVp_Sjun`7qdkbPCB>IZ6WIP4!|}k#zHzvA?10!Q5hFG1 zRKAg-f0rO;ODVvz`nM^ezEQSui-|@0Pl_|rC^w@#9aG7!(=nyfaL=AHP8t5Y6vMqk zf+J%)pT8?RqxWM37-=KI6L6hS@hykl46p#q1k1n=U@2Gv7PI^p;$jh?(i|`!%mcH* zTrdmJ5$z~5;62^)o;rr`!40eF+V5{so zjkTz4xZDCZfsJ4TSO;Rj8n7Cy1*{tDVg3ky0-M2BK(FW}y)J^8+a8!jVeW;w54;91 z!3$6ie(+%_5cb{xi`bFc7Px1ydvrq9?ii+Igk zU}}w&GG(-9?75S%9cT;M0Pb4mCPnUGZV9-%nfpDsgO)YmE!^-CqY`8l0XH>r6JsRb zYH-VPQJ7XJaSJndKl4GC55387{SI=z@n9;rr6LL7<}E%_P=}kjdcxiW(+Rv+ffa!H z1$+RXz@OkFpx>WiVyG;}@$!oc9C25e1vmpU&~gC&abI-`z{i4IFmr+&AiG6|{b8x< z!Mal#_e^~$P!f~?#pU)NmTHk@a9IwN2W8cD1(;N?3~B)G@~jG~f$E?>s13Nmhug+$ zs{2|>RtF}psaF?pn>qEl&D?NH9b89h7Tj;%6mb7JcMQ?7;VB)`k>QYm(s2tA3UVP2 za)KNn4ELE~a!)k#hlvOW?Li075wJj_U`B!=%+SFW@jGv+8aWKt+z#{|U<=#~cEY2n zxaVe^$$%>qlVFYl6G3L&Pk=cdd=JKe(O?`H3)q+_rx^{iF#I&`*<;w?o^OG~;#ACO zIu!W&ryStsmif5n?i%h6;zq+cfIEX`0sf9^{uTU(zk4aA;sr~t&D}3pdYLn1Lh|~y z_dnA9Y3bk0rchsRKW{AKH;o1EV-OBqx577M5_ zyh60W*>O^CwjJRs?$5}pGuUdxU z7@T6)EFO{UJ(Iz4bJvqQKKb9QYlN$J7-?ZMzGL617u$_WZ#J>Rqi%ZCA-pGv@-4ME z=b+(k8R5p?+n*(!1vc2S6?LlPpb9}>-r$58q$1ec-`B|xHh5JY6*&J;&Y@>g)-jvd z(2~gS*DRSlOW_hrPf>|W3~oR9@U0Ch1@N$%B)g8NHxy5Qs|QZtD0STunuxW-*V|tf zU$+F|u#Ah)@MH^O+*)s%JEfGVxLFGsYG{X&>W0PNa|sj}wUFP}|M|<&@2^0?7uo3J z?Xy;zLji{>O}c@gj>sw)o~NPCTz|AFZ&r^R10U)BK^yP5uTt-wyoW1uGOKvsw78qo zS*6x&tGl$kX$dfAvC8zD7C&3hUOmFQx5ZGnJNKRkUdvxF%m8m+e{Y{)tNaQLoWJtv zCPL%pJ{DnwwSTp+=V#|?kz)}%br9cM2(7K~0g9w=EgdVtI5MQPyvz@EuD=vpI=8yMxrHOd?%j+C1R{ z+vktDGNc^b6HDw#yzv$&h8 zN~tPV57~RqlF?L8F5g3uw1PjZFPLM^jj{|jF9N~TB9e=h5%pm8RowEW4vTVKIqv|U1g}P9(r7+ zEB~2AJx+Go&`gDmhMhT??0jr#XHMrXxt>`3JXfIFu(w$0re&1~h7J5KWs}gSsMDWh61*^{$Rw+uqFSIX9fa7dYK)|MX32!(<_kWvREO%o zXQ&<%(Pmg4qY~wvTYb@nW$+W-i8sdLi?SAa^yBk0_~qs$?$6;Ds$9r(OGr?>>Cif= z-@Wv~q0P8W4Z<(YeWImMi>9isws_rY1F1(gX<6Qy*6NRLzpZ$_Kn!1J(|g22U7O6T z`CIM*@D85o?N6Fc>j$ zC!t`vEf1;p6ngA*tG4Tzp-EF5F=$d#0;dm><)y{n=A1+K$iK$DHH~r=V5$0h_w(+D zyvre7U!o!4)SMkJkxhAX$k~_3CjT6Abc)s8vm{)yDXnrHlJ45-O=HX^gwG;#sxKv8 zA?$D{aMb?!WRGV<@1?73Hu+)NLWN-x0R@~6G?sd6p~pC`b^SbT%7cx|5e1Hpn0#!L zU9T`OoPq*gX+&LnQlQhEDThx$fejr#U6&NEQL`W7NJ6CL1N2zG#xxyyyzF-$E@^4; zLltvMoKvD-qjPe@oYEBemNlnbd2Pv;Js&h!YrgJm4Vx{J{|#c@ z9aB^W_WW7ST?_q#IOww%LkSF#7Emzhg%$~6VB6e!r+Yke*<|hJKV4upHGqUk8Vr+p zRQ%M{Xs`4YeC#&UVT0-xHLT?Gb{Bn4BYO=un_z>Q6E$X9n@T|ij?}Z;oP!Mqm0^og z-D~&$eLvVpino@mIH#`ATXbTdVb4$_cYmp7%F(ifmO;qKg1#y8NSn9FARAuuu~YYc zJgH;wyLuLty8awz*@8R!V=rhvKHjj>;nfP{LObV^X$cd=E)3@9ovoCdG zyTW6c1O;XqJ`x87bizv|ZG(BB{8%!y7%C6B{!agASuaCZGqL_vlJej*b;J^7FQhbQ%P;w>5X|Op30{^wfdVH zNp=&|)^qqn3F%s_XHf(-xYOE`4=;J%3d5UQF< zEBVtIG1rH{xCQ7~avn0>VhzxX&jZJ1-nLk)8*R-|&nRIzX0>KC6jWn;DOZyqu;ubY zau{0Er22vsxch6f-6XqGI;yb6#*Llsspm;FQ}(}=+l)Uy<tmUi$}u4hX^rb!e7R_}lkQTD%|&Y`g{*~9 zm*UN@zt7okWY^z2#!WhI)A%D83|UowLm$(T*vjQZ?03AF#L~IWg}#jvcJy*&uZ1M)`zAt zd;i4n0gp@FvPbS8R|nHKnzd1)2?z7{am1OQe;sPr+B_GaFJ^b#c-Ir_oGXtx&*5Sj zdUyT74@X81#Pgr$q3U|yIdNvC4lg`c7J{Cd*PfKM8PNYXuc3QXvv0n6fhX5~h5~0) zh53a02?}PPn&Rh<&R8F3aP(-TJ4TO6@*|9(_qFxs<0%c6nJO_KhBM=c)gk&_;X zaMgO+ex0a-wh^H-Cho4JB8-8knPkam#Tp+JxCj`1?$@RhGd<63SBQp<8*Iw>t;+t> zj&yVEHVdQ+oO-T;0!OAyy~D=u>Gt+#y8=3NDB$6mdN%il`Uq6#_L~Ji{IM$lddz*q zA$vo4meJ}SSOgke1IfRl_3byk7cH`D)P_x3*woxQcVosg^}=DpCsep?D-5;T5`z}+ME!am6uS!8eVRjwMCZbruxME>x_46hPkW0 z&Qr34mv0c3RKI@oFl>g%(3aNpnd2?Nk|q2x&iY|7%`Fqw7TlUkflOBIsjXrrYrZ62 z&GiQjZEYxRB5iVDO(9b=S^aDwp?cOIY4bkoqzX4@A{AUMM193GA6;iRTrY#BEAppv z@zpWC9%;|%tWubMXf-gcl*?=_V$RS~hGe#enDexhqnQy0|CVwmv(?YDT1&l>P5%&@ z@HQLzQkF$(j|l zppO*GYONmlq?KL^vZvko!@NIEa&?eT|47rt*81EhU+_hjjfwtjp<;nD)_h1SC$n0! z;Hz)X>6>oY>L}j|SN-*g-|US2FdxNijp^1GApFeb+e)u&)(~5UcDnCL?>Ed;YW}zn z@Er>>tU)gABvuAgS%IR=_xx3WLh5Mxuax5oW%8wCxD~h;P=GyMro08kZI2s`}=)Fy2F zaB28#?jbuV&)P%g(nn)ewR;a~8SHRx$hYgMY>_YtoEluEWfdj8d@S|(pqjU%({ z!Igpy*MP!`eyLRAk1P5jh*q)<`iM_{lu8$+k?X-o+h#8p{e6n2@f~bzaJ#i*zEn|8 z!>-$XHS*FZjrn~fIxqa%qg*VGXj3*t^n8?1CiNQATe0mU-vip~1J@}SLx%|6?85K^onAi;X zr|m+y`xh}tz-QTA$eKE-%MiWT=MRx6Kh*y%L*&X_m?wvbs}B--6ZY)ZR{VB3gR|3M zzC%z6eLF;Im4;?mq^$F`w;Wp+Y@XmWWLaL%=IhTi=A*Ofhz3T=YWS&Mg_$Qr$~E5V zFNUPu0#qxbq)J9fEq{1wl%!c}Y4&>+sLh;2?~ij`|Cs7iz8g_y6P_KlKOf=g8mUhpO=dlKKNWM^j$wK)TyfQ~&ZGJr7`z5?q zUX+6x4UOD1TAS+DjhB!aM(PvXCY?+<{QQQswAbopa-AVS-?brDYZC4ubVXY{^L5oe zRFySF%izL%=E3Zoj|Mdcjvi@Uw5x+X$W^i)3RrbH0>hTDUILl*%^GZLK1Oeife)uI z9I*ceUYr`OvC|kiQ3RPd3>sX}fA*qbgBc4aVKNoUNfKrs6UK<8D669Wid1S9wbn47 z86)$HqG*)R95<(pcBh(>bS;LOUSL_#cfn^o9Vw%{_9Ao25Ga=*y8xCDgX1<{*BhGTCvd7wZcWYmA9ver_D>WW1_j$W zXmCcEGHOWZ+N+^>v^H`*P8a*l+N)XGmPPATILWlvsf*35b_#x}0mX=M96#fB8%Fh` zcj@GK8LKs}#y4_PRb44w)*4_-H(7r=FHxZHfkmITJ4D6ET%)E>m@K=?Vwm~+Z3W83 z-?u}t+_9w2(tC6Hr?xn&GUCFfUM)rC_Gq{nJQPx zA%1v(eOJz!&m1yUa+J6FB{jBP=x<}&1udPfKZIR>eb{OEq)vEety+)MkIJS|fqaj* zcX`>@l4#AK{nz^mOs5fUe@|bQw|sVLh6T58dMt@DI@obpPnn$C|u4;ep35 z<>_siUJ&e!Iq#6{qH2cTx*80T|e4NI*qvzZ}nI>CYLJX6v~Tv;5_#I32&|vrGKe_dQJwMFHOSfjTC4D8Um$~^7C=Nb$+g3qyqYh)s#x2>*NauG`K_%NqJ!2dR!O6Jd|mqtn|Mn^dk$75;`w!n>_7l4Z?(R# ztEx4NQ941Rk$>r7H@8vIv*vxR_1w|?i?>uX8=V16j1U-S-#YQ29`IRB9_U<5bG@SPs^lMb(H@8Wzw-a8d~lZ zGMD#dSIF*~@S)8LeU-6H+Ew8h*ESdkA5;UozEU1R)0PEcBtsY*-)FuM9W{50tJ+Ue z(8qt3c-4Skl~+m2+Sar#+>ViNnWU@*S>sjG6?Q=bR_QTpJYez9uhU(L(PM}uF{hcZ z;pD&4jm{PF?b*E5unBfrwo0Pu$HrAspf=2XtK=EOL7I-%fq80`+Y&;ReU(=?3<1mtZWQJi`EPWj;HpH_mhD|%{)4yI8 z;|dfPr&Ps|>3GpnXg>fvU~%a5^s{?_0bdS`|twehVE+Wxk(?Y63B0qpT3LD ztlFp>G#Rf@60 zMqO`cytKjK?YUi6!>uhJG&r2jKe?^@$&_6uz%2*uAnelLF4v%8uD)G9G{gX;zqTMOfHAA7|@3*|hYkYLKSkhIi>wMkM?F91X0OolU?_!?!VyAp=q>Ych zjgeDzcS%TNtGjQ>-Fi1w<(Hl1*PPyoO`Bgb2ataBi9;Ry=*)7=%a z(%ld04I%jFM4PwUYW@NZ^u}68eNaM&VA5UAMWS0+-D4-+5eKDe3u}2(q)cpK^@!a9 z{fDf_Enc-8X<=<)IHKtjX7%!%a!4=P%rh@t>$g4KeJvPm0a<$+mOriovmQTpF^5@G ze`To($#h!6+M*>zx4{~rk!0O2Uz~ePLbXB^m)6$waqPa*HR<`U>E z72r5|-pZQ)AG`f324+_R_#>?jR*8KQ<=FRrjtZJ*adEW2h z)d9`cc-l5hqu%Hls7lG*JaE4}=?cHJ4n^BVulF7v<_4#w`ykk8J&1={?>*dAU2)fI zE!G{i9>d+-`LvWCjF&?@!>twnaq$|yg?fIY-plrm)~u=kj9|sJ)4vKvYb@@vx|6j) z-0CXpI)5!hT`={s=9S%@t+s#UKyUEwdXq>ewYpg?GH1fSiDSI+P`MrYFLKoDoXkgo z+JesM<6rWmZA;oZWO=KP9UNZu%rHtmwm?ry)^6xhwMMO{z*Y@@xMP&t@pj4k{udgr zQIiY!(fXWp?}l17@SJ?#&H8WRr|O|&I1s7Tv+*)chnAp%%Fl?|sBmY&289j#4ReY2beNj=gNyb<3A5))MeS-2R{6@o}wRe4EC?NW^_X`q3?g+=KdOPZ2QoLX^(%~^B9>Izo$mL z&Ev1g(f&xYYFF~P|G!E{)PS%1u>YX%n0Zw`M zqr~)lRMp+c0Eh0tYEpTjh7_~IM6}s=*3kb$6H#OQR0V0IMjI&nB|5@d;GefyiMPCr z5aO1?U#pI42VafHUw7Ynw|cFYHRzwmEVk(XQJ{{E9nTH!|7A6fGbH_+QN^gSaiaY% ztLWd%apF|Of03(tZTa7jAl2#axgj4%Aiq^D{2%LV|GWG%s)w2@8cqH`&&L0(l>gxj z_J4P@;#9=BwM% zC>l#QDeuTQ+}q+VTx!o~c&QfXl=F`4hDK2E9sMb;!_$pV>jd=DcU>^9PL*Jj3Za#r z-}$h|yUwq*(6mMD26rUoB!u#pcT;Jl+a#;i)(Wn;FE+lPwhkKjK@xwL9ywbIOhyiWYV5na( z7JvictG>)X^!I}{7iVwA75jj>OrPei#7xG^&USa@<7A{1KbQ8wuRwza!7rA;bl0dd z{>@{scVP&B66NRPbWw%!-It%{{^_2sEBxYeCRV9Xq_y5y(`Clx->w#`Uz?hH-j_R5 z5blWkl5r|bJlWQmit*f_+>NRdlqatUf z?!c#UVtqHl-vkZ(jx#Fhv7n3fLsRXtYZx(Ap?o7vlV3?`aY$3lD}9IV?9IvknCSZg zJ1mVfop>b^pc!-*8hlqAy!dXOWig*u*fn0E9rOKi&yAClHFnQ{vmp$(pI^x(xcx>v z{&`G|cqAO!*ZqkR4fY?0x+zW>tM62FP$Sky|U2i377Q!<2fS!J< zZ!#V->fP}rFEf6&x0~Ba?xz^u>npClZxS)vWyt zyW33f#D(7T<(58hmTF>b+WdjeG<8iQD@X+!|;q_iVD@N*TP`G|l~AnpFt z-zzN`aw%J-Ar>ZEWp|uit)2<*YOO6_=3}L@Z9~2PX2)BIm4bYZ}t9Er8{;9`|&>|W*+jxh_;adarg15WY`XV(qEJ|z1<-CLH(?F^<+f< z|8xTJ8+8s#dIJ4y$B_lB*49K3(c4R`4C9X=&<$XvEKU;T829w535wC;#I_JZl_ayO z4W|3jX`!{cb54^*+5u9{tDB{7Y#+xRAu&r8vQiY5}jW!ihY zw#)whXLTOto{8nyGQ@5~Vv~~>e9m8K!c<$epy%*ePe9=%iDm9`WK~RJvB9(@Nn+Bb zK`VYty=BkwY?z4VLmK#pchj|&BOS^`P?4l2t#);~@bcW)Pwgk#HA7&-m#c586kT5S zw_@m`9sGE-9O-R-1?NK{Mmgo zZ|!nl%aYOay-ifrnBPsS3~u!}WYUkSAqVi} ziu6w(NtILEgxSZLFPd6NDrvbIi%hBH-73VgV=5`I8o8K& z15|3=fuA`{b5Th0ud%u(!q1&>I$SEbvDz9%n>K5{PO<#D2HRRDyG@TlX>D{9uT2PN zubW9*3opL0e2k?}i2`O5el8!xA30xelN!`~4b6Qplctu^=U`@mx!&q0yVs*}uTL$} zr(%Wf=EJEa^IFWsv!^j>vzU5q(!Y3JAYhnEFCtkYjqLo{!9{~KGJh@Z!y#V>b7&fQ zhKQMGr4gUgNQ5r;GnYs!J0O>?>##Lh32o!j>9Jqav`bir+QOkz+oTcbWW;)LItkqn z8=Rkty}LPmdYP~u^+%;9){NgBrUH62W#tB>+HmCNF5Q`yyzX*r56lYg;{9W6U|9CV z5nI3GzPGy!`VnbS?rd2+^xXNS;I`{KhaQ}7kGA1+T(fLOskQg35Mq5ad^U>J9DlO? z%r88rZ-+Ok^o_E$CAaAv;@;53YmXM(nn^_n)zgS_I5fCHF=*3|hkA^fT+be5RWK?F z_5#!sZRB)pf!fZ%CpY+%I&AOHpWb?0VvW$MQE%GkbsbP~a2~tn zJ}-HO&~2BM#(`Gv>m7DY(bBG=7k3bjz0r2Uos29IGj>=&AG<;p*zi?Yjr~a;HoTju zq1`4ptJGjssh?F!o`e~v-{=L08Q^fujc&72=X$bGbEu_kY*slzhpV#66UP4#G&$Io zZhPQ()3CD{bWJo=%bk%6*-`R?_;4V5c9l$rJju85-RE zlC$nR*N7EgdfPP)WRvdj!))}4cd|({c6&w#V042<4Kq49qc@3LpNx*d==?rsligR~ zU*_x*!w#cZcA2mfX7lWl@+!)iTB z88HuZ+MHebTt#o)XBU2dk#Kiu^f%{o$TfHv+n?xidk<&msiHHx=8|>0p>HJI=%@ag zV85^I4S!We$mFe7Pm}6Jm7OgT4cUg`m^Wm_Z{Ot@)Ji1^os!X?#vhuy%-L)05F4aX z21e5U8a1PHj?G)ywhyDE;mAm@5np3e`nKFYnkju-bUwWWewdK+LECVT_4c%^$|unW z9CF-opwY+JTluBHLA!=6;jZ|vvGOy=aT!~xM)z-&nsO(%e$hKu&J2wHoS7LAJ7B1a zD6VXPx$f8~YQNaj{L{eV1|G*< zP{KpnpT7EJxaQL3S;H>)VRgwE?2LpM!{=Z9j2$i$8vnE+`m3ARblLv#5NHsPlQ zL;S`20t$bwzeF8F*Syo;#Dj;UlAbselw^0?GWPM|25h`wlgo2Sly~cDt?dJVIY5rV zZEP;HkD#9pMTUveHTGw5GuA=Hu=)}pkB*~@ON}Fo*?qT}T*7?mQ}f&Q@Qj>va2(hF zxZ|}NTg`tzg2o*NRbaM+YjB+L&#b!2Z;VuGgfgpf$o!v+{M4xx)_8lsbQF)A}s5*!L4|ED~+p|#*)V$l6 zJO6|B-K2=rx`gf};VJU}pL&4*!5YJPrdiD*cqRfD2Q(2 z7w=J(8n#PwOnXCujsl0q!-g})$IS)Z)w4p!d3#pY^C0SSM` zQwSzk&~FWXvhu~u;>Ybak;TO4IugC8nC!fTDzXKd9Dz0z|1)AsQ2vkFLJ^;1oK6&z zA<(qlg$5sz&lGvSyL6syRqPu08bNpXVNPFMj#4vjeC(Qm#i!rEz+0`j{(RLX)72LP zeu}}SbL}TB2&@%sG9!@1*G}BMx*{Bl2Zl{laXA6EwwcgiHk@f3FrxC6vrFw7KNXkx zH|>w%e-!>>$bZA9KsGkl4ApOBuCeM*RbXEkNq!qEpW1Pj z>81W{YbM*&vU)DB*xvHNqG9d&Sg>B}udODmDk~FiBd2zkm5_VL)2q`CS5?6{CW{<@|*rbQez(=i~B_F z*XX-fdA-`&Jl~JK?VswbU868;xDs=1PrA?Fo$GMRZd0Yacq4|kP-rk_)%u#M)_!@( z)vi&eg0#AeB`uW(vr5x9QmyhOHlI|!eIsX$ypQL1aN3hQj;X39Q7E0DuYV6`ysDX7 zO@F3Ol(t3Mf%nT|br)M+wdLJs)#Mo64h%7A2YIy}a=&kn#@D&ufl@?qd}Z$9sJT(>7tU{$6Urf(`XQ4L)8UF8F&V zv|4P7cmx-={qU3B&efSO{FX*8Ee#Dd$2k!qUJvk+-syq<+R5Y4q$HO|tkZvQrESu^ z86pcGAkT4H_gR`RLnP@#n3n2N@*!g5T3s6P-m|)ldx%)&tu7aMuQt{PEyUsmw@_p; z-w3V!|9d{JjT7Prc`{4T?V;o>RH}z z>+4`^(JD+L3lxjn?`!CO{&+ZYa@qE)(d{83+P)IFje#FQ32QW{qxa;ivNl@yVZ;}n zK&RSh>pJogZatqvgBkEJxtB+>VLAPvp)y}PF3`i~RZoBK(4h8_8ey&*xyeDD>X*Ns zw0VLO_NuRI6k1kt_ni@~@FR0=3pKK1eSJCl1gq~&8%T|(NG!HRba;xyC+a41aBn+- zlIOd$yD|MIHM|jlo$Cl(t7jxxeKF z&5KPW*9*M#cnBBF#gmmvE?!YK%SQcVG~|GjcF41bEPY|EVXM$o@BZE$OPX(HjZJ5@ z5VhJ7)>K?yB11+&BNzPHQM~%oZ5OW%QW~g^Ynn>=msoDa`?}TC+yYI$iCy09?Dmrp zDZHS``U1^gn#wh5EK~3FZ#~+Uaktl}lZ=!0PQ+=@UHSY9#c{H!c*9J44}LNB*A6%h ztv<6zwApm2sWf?o-yxT5CevRbH!C;OHI|R)m9D`0es#3av^t2lg8aR`+3>S=GjV^7 zUotmoCZVsbqs=p#$-UResq4+e_6D)agO9zYMp(gn#%`Kk?)q^RZ)BCe@5eo87c|(x z-pLwXa#Xez<)Ohk8{p?OEmUs_9eT!m`H*T=IDP`it_0oEyil17-y>f`gHPZk4(I%% z+`LJxEv6=jIXjnh_`oa&t7A8cwHV&xz)ic2A8h!G^DQSchO{2qqlMk3Hf%U)a4Hu* zGh^V;Ja(Hdu;GMbeMxiedsUq0D;o)XYYjFZY9(FYB1_J>^rTX*`{vSijX|(smWOXGzC6IC%N@JTgf=n`Zfy&d?+aH9>G&jZ zP8_Ih#O$XwvYWmifd-qz$px;N_UE}@)2?wtg_|#R9)Hu=n+xnVZ`w%8_i&rMtsb*h z=|3h(l_l*PyM`BR7_+<6d%ajt>dkh$jbB@72Di2f%I%b5kFs|hKWnsIqj6h_rth7U z#-TS+Sq3exkHaU7xJSZq8LLihq~!;MpI)Wk{lf>}I==?BwQIy%nwr~EZ6t%cANGAS~Yzdtvo z&o6ej@s_6Mc2FDn2)DKgD%^|1+g0?PeqoQ@?ZP(V^Cx`&N%_92VtDf&rE<@)Ys6cc zn(sH-$Pl`Hquh3Gx$w)`Nn6X<-Nsv*np>~7aujZDek$KbTUK{y;Z_vKVWLDdjS6k2 ze}w0ap}=C_b9>VAG#M(rwJXG1n3~hbwo-#`Co8u>AxAeYn7na--ECKVKAH`n)~Uc; zMe;wYihe_lWY}gg2X1YrpuxUi`lf1&5(n?+aDyI`C$wMbDJP)84H?ul@9HI%Pna%L z=p%JLSvQ(P`%2=^Xv!V?P78JMu>=II>nq(qBRZjd)!fCL=-SqfX{M|0%pad(?x%NF z50(auJeYVQH_>pjBy8Yz=V$zGIDbEx@CAV^>@SzTAbK(QJ~kh_h8A3W`RRgs!CLhA zqkgCD{inIQxZ4guf&Fx=JI_O!Rp@~p-56+fFWvR{&9Z$fRt(eK{BD4Fn_S#I6Ajd3 zx$xnD{JomJ90f1g*&@u?V^-IiT=;34nw`mpT-cU5HWAG#Xrlo1b+q5(rG%cGm@+#h@ zrD=3%BekFr6mPevX~f&KG#fOnxpW(E)6z8JZCaWQn${!6EZ(N2X(VqeUKaQsZ?~vv z#M`tqn+k2EE8WK1wls}++m>d7wzUIpZSl4(O~X7wo90C9&7&hF+Qr4sb`BbBws zr+fy`{YWSK61ilm74NQb#?a^MQ#QtZuQ&3UFu9$l((X_hm@Yr_hr5a~-(UQ__#}2Q zzG-DzA*~a;_y-Lfs}B{cFQgCL^QOj0K02crVH}zS8?M2e4EnL`u46Ak?KUgM%2D`a z+YJq_!Th|saw%KG!t?AJ=f_S@f*g3NyeL(0MdFSZGC#E|BpRnb?`@ma*1giyj{EF3 z*~Uo?xJ_C(l?x)_FKS!Y^MbvSJvr6DBY~$?f!ghchZEx7uo6S!o)$h*iBE2WmlR$;VfI*cCAvj zw219u=h#>TWFacy`Vo4vigk^qE3mUGZKOu1JBs>rzc!z nW7{6`hD}D!5ZUEu-Y5p@MwZqCT4Ja-J#Z(R^7aBQ_UC;7Zy5Qf delta 92719 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 MY{Rt4?vDF^0ASQl)&Kwi diff --git a/web/drizzle/0035_fearless_golden_guardian.sql b/web/drizzle/0035_fearless_golden_guardian.sql new file mode 100644 index 0000000..47a9c77 --- /dev/null +++ b/web/drizzle/0035_fearless_golden_guardian.sql @@ -0,0 +1,14 @@ +CREATE TABLE IF NOT EXISTS "comfyui_deploy"."user_usage" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "org_id" text, + "user_id" text NOT NULL, + "usage_time" real DEFAULT 0 NOT NULL, + "created_at" timestamp DEFAULT now() NOT NULL, + "ended_at" timestamp DEFAULT now() NOT NULL +); +--> statement-breakpoint +DO $$ BEGIN + ALTER TABLE "comfyui_deploy"."user_usage" ADD CONSTRAINT "user_usage_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "comfyui_deploy"."users"("id") ON DELETE cascade ON UPDATE no action; +EXCEPTION + WHEN duplicate_object THEN null; +END $$; diff --git a/web/drizzle/0036_flippant_meltdown.sql b/web/drizzle/0036_flippant_meltdown.sql new file mode 100644 index 0000000..8f0d8bf --- /dev/null +++ b/web/drizzle/0036_flippant_meltdown.sql @@ -0,0 +1,22 @@ +DO $$ BEGIN + CREATE TYPE "subscription_plan" AS ENUM('basic', 'pro', 'enterprise'); +EXCEPTION + WHEN duplicate_object THEN null; +END $$; +--> statement-breakpoint +DO $$ BEGIN + CREATE TYPE "subscription_plan_status" AS ENUM('active', 'deleted', 'paused'); +EXCEPTION + WHEN duplicate_object THEN null; +END $$; +--> statement-breakpoint +CREATE TABLE IF NOT EXISTS "comfyui_deploy"."subscription_status" ( + "stripe_customer_id" text PRIMARY KEY NOT NULL, + "user_id" text, + "org_id" text, + "plan" "subscription_plan" NOT NULL, + "status" "subscription_plan_status" NOT NULL, + "subscription_plan_id" text, + "created_at" timestamp DEFAULT now() NOT NULL, + "updated_at" timestamp DEFAULT now() NOT NULL +); diff --git a/web/drizzle/0037_eager_cyclops.sql b/web/drizzle/0037_eager_cyclops.sql new file mode 100644 index 0000000..5a3a572 --- /dev/null +++ b/web/drizzle/0037_eager_cyclops.sql @@ -0,0 +1,3 @@ +ALTER TABLE "comfyui_deploy"."subscription_status" RENAME COLUMN "subscription_plan_id" TO "subscription_id";--> statement-breakpoint +ALTER TABLE "comfyui_deploy"."subscription_status" ADD COLUMN "subscription_item_plan_id" text;--> statement-breakpoint +ALTER TABLE "comfyui_deploy"."subscription_status" ADD COLUMN "subscription_item_api_id" text; \ No newline at end of file diff --git a/web/drizzle/0038_yummy_darkhawk.sql b/web/drizzle/0038_yummy_darkhawk.sql new file mode 100644 index 0000000..e7e2c0a --- /dev/null +++ b/web/drizzle/0038_yummy_darkhawk.sql @@ -0,0 +1 @@ +ALTER TABLE "comfyui_deploy"."subscription_status" ADD COLUMN "cancel_at_period_end" boolean DEFAULT false; \ No newline at end of file diff --git a/web/drizzle/0039_nostalgic_lyja.sql b/web/drizzle/0039_nostalgic_lyja.sql new file mode 100644 index 0000000..37cbdc2 --- /dev/null +++ b/web/drizzle/0039_nostalgic_lyja.sql @@ -0,0 +1,2 @@ +ALTER TABLE "comfyui_deploy"."workflow_runs" ADD COLUMN "user_id" text;--> statement-breakpoint +ALTER TABLE "comfyui_deploy"."workflow_runs" ADD COLUMN "org_id" text; \ No newline at end of file diff --git a/web/drizzle/0040_salty_archangel.sql b/web/drizzle/0040_salty_archangel.sql new file mode 100644 index 0000000..34acf4f --- /dev/null +++ b/web/drizzle/0040_salty_archangel.sql @@ -0,0 +1 @@ +ALTER TABLE "comfyui_deploy"."workflow_runs" ADD COLUMN "gpu" "machine_gpu"; \ No newline at end of file diff --git a/web/drizzle/0041_thick_norrin_radd.sql b/web/drizzle/0041_thick_norrin_radd.sql new file mode 100644 index 0000000..dafde7a --- /dev/null +++ b/web/drizzle/0041_thick_norrin_radd.sql @@ -0,0 +1 @@ +ALTER TABLE "comfyui_deploy"."workflow_runs" ADD COLUMN "machine_type" "machine_type"; \ No newline at end of file diff --git a/web/drizzle/meta/0035_snapshot.json b/web/drizzle/meta/0035_snapshot.json new file mode 100644 index 0000000..9d920ed --- /dev/null +++ b/web/drizzle/meta/0035_snapshot.json @@ -0,0 +1,894 @@ +{ + "id": "2b2a5d0a-2494-45ea-9d4a-58a70df97829", + "prevId": "8d654f92-7f7e-420f-bbd3-73b6b27adf35", + "version": "5", + "dialect": "pg", + "tables": { + "api_keys": { + "name": "api_keys", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "revoked": { + "name": "revoked", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "api_keys_user_id_users_id_fk": { + "name": "api_keys_user_id_users_id_fk", + "tableFrom": "api_keys", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "api_keys_key_unique": { + "name": "api_keys_key_unique", + "nullsNotDistinct": false, + "columns": [ + "key" + ] + } + } + }, + "auth_requests": { + "name": "auth_requests", + "schema": "comfyui_deploy", + "columns": { + "request_id": { + "name": "request_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "api_hash": { + "name": "api_hash", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expired_date": { + "name": "expired_date", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "deployments": { + "name": "deployments", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "workflow_version_id": { + "name": "workflow_version_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "machine_id": { + "name": "machine_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "share_slug": { + "name": "share_slug", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "showcase_media": { + "name": "showcase_media", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "environment": { + "name": "environment", + "type": "deployment_environment", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "deployments_user_id_users_id_fk": { + "name": "deployments_user_id_users_id_fk", + "tableFrom": "deployments", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "deployments_workflow_version_id_workflow_versions_id_fk": { + "name": "deployments_workflow_version_id_workflow_versions_id_fk", + "tableFrom": "deployments", + "tableTo": "workflow_versions", + "columnsFrom": [ + "workflow_version_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "deployments_workflow_id_workflows_id_fk": { + "name": "deployments_workflow_id_workflows_id_fk", + "tableFrom": "deployments", + "tableTo": "workflows", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "deployments_machine_id_machines_id_fk": { + "name": "deployments_machine_id_machines_id_fk", + "tableFrom": "deployments", + "tableTo": "machines", + "columnsFrom": [ + "machine_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "deployments_share_slug_unique": { + "name": "deployments_share_slug_unique", + "nullsNotDistinct": false, + "columns": [ + "share_slug" + ] + } + } + }, + "machines": { + "name": "machines", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "endpoint": { + "name": "endpoint", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "disabled": { + "name": "disabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "auth_token": { + "name": "auth_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "type": { + "name": "type", + "type": "machine_type", + "primaryKey": false, + "notNull": true, + "default": "'classic'" + }, + "status": { + "name": "status", + "type": "machine_status", + "primaryKey": false, + "notNull": true, + "default": "'ready'" + }, + "snapshot": { + "name": "snapshot", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "models": { + "name": "models", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "gpu": { + "name": "gpu", + "type": "machine_gpu", + "primaryKey": false, + "notNull": false + }, + "build_machine_instance_id": { + "name": "build_machine_instance_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "build_log": { + "name": "build_log", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "machines_user_id_users_id_fk": { + "name": "machines_user_id_users_id_fk", + "tableFrom": "machines", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "user_usage": { + "name": "user_usage", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "usage_time": { + "name": "usage_time", + "type": "real", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "ended_at": { + "name": "ended_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "user_usage_user_id_users_id_fk": { + "name": "user_usage_user_id_users_id_fk", + "tableFrom": "user_usage", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "users": { + "name": "users", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "workflow_run_outputs": { + "name": "workflow_run_outputs", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "run_id": { + "name": "run_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "data": { + "name": "data", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "workflow_run_outputs_run_id_workflow_runs_id_fk": { + "name": "workflow_run_outputs_run_id_workflow_runs_id_fk", + "tableFrom": "workflow_run_outputs", + "tableTo": "workflow_runs", + "columnsFrom": [ + "run_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "workflow_runs": { + "name": "workflow_runs", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "workflow_version_id": { + "name": "workflow_version_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "workflow_inputs": { + "name": "workflow_inputs", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "workflow_id": { + "name": "workflow_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "machine_id": { + "name": "machine_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "origin": { + "name": "origin", + "type": "workflow_run_origin", + "primaryKey": false, + "notNull": true, + "default": "'api'" + }, + "status": { + "name": "status", + "type": "workflow_run_status", + "primaryKey": false, + "notNull": true, + "default": "'not-started'" + }, + "ended_at": { + "name": "ended_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "started_at": { + "name": "started_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "workflow_runs_workflow_version_id_workflow_versions_id_fk": { + "name": "workflow_runs_workflow_version_id_workflow_versions_id_fk", + "tableFrom": "workflow_runs", + "tableTo": "workflow_versions", + "columnsFrom": [ + "workflow_version_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "workflow_runs_workflow_id_workflows_id_fk": { + "name": "workflow_runs_workflow_id_workflows_id_fk", + "tableFrom": "workflow_runs", + "tableTo": "workflows", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_runs_machine_id_machines_id_fk": { + "name": "workflow_runs_machine_id_machines_id_fk", + "tableFrom": "workflow_runs", + "tableTo": "machines", + "columnsFrom": [ + "machine_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "workflows": { + "name": "workflows", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "workflows_user_id_users_id_fk": { + "name": "workflows_user_id_users_id_fk", + "tableFrom": "workflows", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "workflow_versions": { + "name": "workflow_versions", + "schema": "comfyui_deploy", + "columns": { + "workflow_id": { + "name": "workflow_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "workflow": { + "name": "workflow", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "workflow_api": { + "name": "workflow_api", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "version": { + "name": "version", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "snapshot": { + "name": "snapshot", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "workflow_versions_workflow_id_workflows_id_fk": { + "name": "workflow_versions_workflow_id_workflows_id_fk", + "tableFrom": "workflow_versions", + "tableTo": "workflows", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + } + }, + "enums": { + "deployment_environment": { + "name": "deployment_environment", + "values": { + "staging": "staging", + "production": "production", + "public-share": "public-share" + } + }, + "machine_gpu": { + "name": "machine_gpu", + "values": { + "T4": "T4", + "A10G": "A10G", + "A100": "A100" + } + }, + "machine_status": { + "name": "machine_status", + "values": { + "ready": "ready", + "building": "building", + "error": "error" + } + }, + "machine_type": { + "name": "machine_type", + "values": { + "classic": "classic", + "runpod-serverless": "runpod-serverless", + "modal-serverless": "modal-serverless", + "comfy-deploy-serverless": "comfy-deploy-serverless" + } + }, + "workflow_run_origin": { + "name": "workflow_run_origin", + "values": { + "manual": "manual", + "api": "api", + "public-share": "public-share" + } + }, + "workflow_run_status": { + "name": "workflow_run_status", + "values": { + "not-started": "not-started", + "running": "running", + "uploading": "uploading", + "success": "success", + "failed": "failed" + } + } + }, + "schemas": { + "comfyui_deploy": "comfyui_deploy" + }, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + } +} \ No newline at end of file diff --git a/web/drizzle/meta/0036_snapshot.json b/web/drizzle/meta/0036_snapshot.json new file mode 100644 index 0000000..83c5d7b --- /dev/null +++ b/web/drizzle/meta/0036_snapshot.json @@ -0,0 +1,970 @@ +{ + "id": "4db08fc3-2444-42da-b742-f1832ad8caf1", + "prevId": "2b2a5d0a-2494-45ea-9d4a-58a70df97829", + "version": "5", + "dialect": "pg", + "tables": { + "api_keys": { + "name": "api_keys", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "revoked": { + "name": "revoked", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "api_keys_user_id_users_id_fk": { + "name": "api_keys_user_id_users_id_fk", + "tableFrom": "api_keys", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "api_keys_key_unique": { + "name": "api_keys_key_unique", + "nullsNotDistinct": false, + "columns": [ + "key" + ] + } + } + }, + "auth_requests": { + "name": "auth_requests", + "schema": "comfyui_deploy", + "columns": { + "request_id": { + "name": "request_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "api_hash": { + "name": "api_hash", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expired_date": { + "name": "expired_date", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "deployments": { + "name": "deployments", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "workflow_version_id": { + "name": "workflow_version_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "machine_id": { + "name": "machine_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "share_slug": { + "name": "share_slug", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "showcase_media": { + "name": "showcase_media", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "environment": { + "name": "environment", + "type": "deployment_environment", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "deployments_user_id_users_id_fk": { + "name": "deployments_user_id_users_id_fk", + "tableFrom": "deployments", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "deployments_workflow_version_id_workflow_versions_id_fk": { + "name": "deployments_workflow_version_id_workflow_versions_id_fk", + "tableFrom": "deployments", + "tableTo": "workflow_versions", + "columnsFrom": [ + "workflow_version_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "deployments_workflow_id_workflows_id_fk": { + "name": "deployments_workflow_id_workflows_id_fk", + "tableFrom": "deployments", + "tableTo": "workflows", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "deployments_machine_id_machines_id_fk": { + "name": "deployments_machine_id_machines_id_fk", + "tableFrom": "deployments", + "tableTo": "machines", + "columnsFrom": [ + "machine_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "deployments_share_slug_unique": { + "name": "deployments_share_slug_unique", + "nullsNotDistinct": false, + "columns": [ + "share_slug" + ] + } + } + }, + "machines": { + "name": "machines", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "endpoint": { + "name": "endpoint", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "disabled": { + "name": "disabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "auth_token": { + "name": "auth_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "type": { + "name": "type", + "type": "machine_type", + "primaryKey": false, + "notNull": true, + "default": "'classic'" + }, + "status": { + "name": "status", + "type": "machine_status", + "primaryKey": false, + "notNull": true, + "default": "'ready'" + }, + "snapshot": { + "name": "snapshot", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "models": { + "name": "models", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "gpu": { + "name": "gpu", + "type": "machine_gpu", + "primaryKey": false, + "notNull": false + }, + "build_machine_instance_id": { + "name": "build_machine_instance_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "build_log": { + "name": "build_log", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "machines_user_id_users_id_fk": { + "name": "machines_user_id_users_id_fk", + "tableFrom": "machines", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "subscription_status": { + "name": "subscription_status", + "schema": "comfyui_deploy", + "columns": { + "stripe_customer_id": { + "name": "stripe_customer_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "plan": { + "name": "plan", + "type": "subscription_plan", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "subscription_plan_status", + "primaryKey": false, + "notNull": true + }, + "subscription_plan_id": { + "name": "subscription_plan_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "user_usage": { + "name": "user_usage", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "usage_time": { + "name": "usage_time", + "type": "real", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "ended_at": { + "name": "ended_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "user_usage_user_id_users_id_fk": { + "name": "user_usage_user_id_users_id_fk", + "tableFrom": "user_usage", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "users": { + "name": "users", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "workflow_run_outputs": { + "name": "workflow_run_outputs", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "run_id": { + "name": "run_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "data": { + "name": "data", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "workflow_run_outputs_run_id_workflow_runs_id_fk": { + "name": "workflow_run_outputs_run_id_workflow_runs_id_fk", + "tableFrom": "workflow_run_outputs", + "tableTo": "workflow_runs", + "columnsFrom": [ + "run_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "workflow_runs": { + "name": "workflow_runs", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "workflow_version_id": { + "name": "workflow_version_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "workflow_inputs": { + "name": "workflow_inputs", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "workflow_id": { + "name": "workflow_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "machine_id": { + "name": "machine_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "origin": { + "name": "origin", + "type": "workflow_run_origin", + "primaryKey": false, + "notNull": true, + "default": "'api'" + }, + "status": { + "name": "status", + "type": "workflow_run_status", + "primaryKey": false, + "notNull": true, + "default": "'not-started'" + }, + "ended_at": { + "name": "ended_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "started_at": { + "name": "started_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "workflow_runs_workflow_version_id_workflow_versions_id_fk": { + "name": "workflow_runs_workflow_version_id_workflow_versions_id_fk", + "tableFrom": "workflow_runs", + "tableTo": "workflow_versions", + "columnsFrom": [ + "workflow_version_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "workflow_runs_workflow_id_workflows_id_fk": { + "name": "workflow_runs_workflow_id_workflows_id_fk", + "tableFrom": "workflow_runs", + "tableTo": "workflows", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_runs_machine_id_machines_id_fk": { + "name": "workflow_runs_machine_id_machines_id_fk", + "tableFrom": "workflow_runs", + "tableTo": "machines", + "columnsFrom": [ + "machine_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "workflows": { + "name": "workflows", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "workflows_user_id_users_id_fk": { + "name": "workflows_user_id_users_id_fk", + "tableFrom": "workflows", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "workflow_versions": { + "name": "workflow_versions", + "schema": "comfyui_deploy", + "columns": { + "workflow_id": { + "name": "workflow_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "workflow": { + "name": "workflow", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "workflow_api": { + "name": "workflow_api", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "version": { + "name": "version", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "snapshot": { + "name": "snapshot", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "workflow_versions_workflow_id_workflows_id_fk": { + "name": "workflow_versions_workflow_id_workflows_id_fk", + "tableFrom": "workflow_versions", + "tableTo": "workflows", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + } + }, + "enums": { + "deployment_environment": { + "name": "deployment_environment", + "values": { + "staging": "staging", + "production": "production", + "public-share": "public-share" + } + }, + "machine_gpu": { + "name": "machine_gpu", + "values": { + "T4": "T4", + "A10G": "A10G", + "A100": "A100" + } + }, + "machine_status": { + "name": "machine_status", + "values": { + "ready": "ready", + "building": "building", + "error": "error" + } + }, + "machine_type": { + "name": "machine_type", + "values": { + "classic": "classic", + "runpod-serverless": "runpod-serverless", + "modal-serverless": "modal-serverless", + "comfy-deploy-serverless": "comfy-deploy-serverless" + } + }, + "subscription_plan": { + "name": "subscription_plan", + "values": { + "basic": "basic", + "pro": "pro", + "enterprise": "enterprise" + } + }, + "subscription_plan_status": { + "name": "subscription_plan_status", + "values": { + "active": "active", + "deleted": "deleted", + "paused": "paused" + } + }, + "workflow_run_origin": { + "name": "workflow_run_origin", + "values": { + "manual": "manual", + "api": "api", + "public-share": "public-share" + } + }, + "workflow_run_status": { + "name": "workflow_run_status", + "values": { + "not-started": "not-started", + "running": "running", + "uploading": "uploading", + "success": "success", + "failed": "failed" + } + } + }, + "schemas": { + "comfyui_deploy": "comfyui_deploy" + }, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + } +} \ No newline at end of file diff --git a/web/drizzle/meta/0037_snapshot.json b/web/drizzle/meta/0037_snapshot.json new file mode 100644 index 0000000..f2eb459 --- /dev/null +++ b/web/drizzle/meta/0037_snapshot.json @@ -0,0 +1,984 @@ +{ + "id": "cde8f758-0055-4326-981d-293ac84db54a", + "prevId": "4db08fc3-2444-42da-b742-f1832ad8caf1", + "version": "5", + "dialect": "pg", + "tables": { + "api_keys": { + "name": "api_keys", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "revoked": { + "name": "revoked", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "api_keys_user_id_users_id_fk": { + "name": "api_keys_user_id_users_id_fk", + "tableFrom": "api_keys", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "api_keys_key_unique": { + "name": "api_keys_key_unique", + "nullsNotDistinct": false, + "columns": [ + "key" + ] + } + } + }, + "auth_requests": { + "name": "auth_requests", + "schema": "comfyui_deploy", + "columns": { + "request_id": { + "name": "request_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "api_hash": { + "name": "api_hash", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expired_date": { + "name": "expired_date", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "deployments": { + "name": "deployments", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "workflow_version_id": { + "name": "workflow_version_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "machine_id": { + "name": "machine_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "share_slug": { + "name": "share_slug", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "showcase_media": { + "name": "showcase_media", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "environment": { + "name": "environment", + "type": "deployment_environment", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "deployments_user_id_users_id_fk": { + "name": "deployments_user_id_users_id_fk", + "tableFrom": "deployments", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "deployments_workflow_version_id_workflow_versions_id_fk": { + "name": "deployments_workflow_version_id_workflow_versions_id_fk", + "tableFrom": "deployments", + "tableTo": "workflow_versions", + "columnsFrom": [ + "workflow_version_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "deployments_workflow_id_workflows_id_fk": { + "name": "deployments_workflow_id_workflows_id_fk", + "tableFrom": "deployments", + "tableTo": "workflows", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "deployments_machine_id_machines_id_fk": { + "name": "deployments_machine_id_machines_id_fk", + "tableFrom": "deployments", + "tableTo": "machines", + "columnsFrom": [ + "machine_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "deployments_share_slug_unique": { + "name": "deployments_share_slug_unique", + "nullsNotDistinct": false, + "columns": [ + "share_slug" + ] + } + } + }, + "machines": { + "name": "machines", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "endpoint": { + "name": "endpoint", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "disabled": { + "name": "disabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "auth_token": { + "name": "auth_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "type": { + "name": "type", + "type": "machine_type", + "primaryKey": false, + "notNull": true, + "default": "'classic'" + }, + "status": { + "name": "status", + "type": "machine_status", + "primaryKey": false, + "notNull": true, + "default": "'ready'" + }, + "snapshot": { + "name": "snapshot", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "models": { + "name": "models", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "gpu": { + "name": "gpu", + "type": "machine_gpu", + "primaryKey": false, + "notNull": false + }, + "build_machine_instance_id": { + "name": "build_machine_instance_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "build_log": { + "name": "build_log", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "machines_user_id_users_id_fk": { + "name": "machines_user_id_users_id_fk", + "tableFrom": "machines", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "subscription_status": { + "name": "subscription_status", + "schema": "comfyui_deploy", + "columns": { + "stripe_customer_id": { + "name": "stripe_customer_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "plan": { + "name": "plan", + "type": "subscription_plan", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "subscription_plan_status", + "primaryKey": false, + "notNull": true + }, + "subscription_id": { + "name": "subscription_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "subscription_item_plan_id": { + "name": "subscription_item_plan_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "subscription_item_api_id": { + "name": "subscription_item_api_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "user_usage": { + "name": "user_usage", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "usage_time": { + "name": "usage_time", + "type": "real", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "ended_at": { + "name": "ended_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "user_usage_user_id_users_id_fk": { + "name": "user_usage_user_id_users_id_fk", + "tableFrom": "user_usage", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "users": { + "name": "users", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "workflow_run_outputs": { + "name": "workflow_run_outputs", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "run_id": { + "name": "run_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "data": { + "name": "data", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "workflow_run_outputs_run_id_workflow_runs_id_fk": { + "name": "workflow_run_outputs_run_id_workflow_runs_id_fk", + "tableFrom": "workflow_run_outputs", + "tableTo": "workflow_runs", + "columnsFrom": [ + "run_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "workflow_runs": { + "name": "workflow_runs", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "workflow_version_id": { + "name": "workflow_version_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "workflow_inputs": { + "name": "workflow_inputs", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "workflow_id": { + "name": "workflow_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "machine_id": { + "name": "machine_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "origin": { + "name": "origin", + "type": "workflow_run_origin", + "primaryKey": false, + "notNull": true, + "default": "'api'" + }, + "status": { + "name": "status", + "type": "workflow_run_status", + "primaryKey": false, + "notNull": true, + "default": "'not-started'" + }, + "ended_at": { + "name": "ended_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "started_at": { + "name": "started_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "workflow_runs_workflow_version_id_workflow_versions_id_fk": { + "name": "workflow_runs_workflow_version_id_workflow_versions_id_fk", + "tableFrom": "workflow_runs", + "tableTo": "workflow_versions", + "columnsFrom": [ + "workflow_version_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "workflow_runs_workflow_id_workflows_id_fk": { + "name": "workflow_runs_workflow_id_workflows_id_fk", + "tableFrom": "workflow_runs", + "tableTo": "workflows", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_runs_machine_id_machines_id_fk": { + "name": "workflow_runs_machine_id_machines_id_fk", + "tableFrom": "workflow_runs", + "tableTo": "machines", + "columnsFrom": [ + "machine_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "workflows": { + "name": "workflows", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "workflows_user_id_users_id_fk": { + "name": "workflows_user_id_users_id_fk", + "tableFrom": "workflows", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "workflow_versions": { + "name": "workflow_versions", + "schema": "comfyui_deploy", + "columns": { + "workflow_id": { + "name": "workflow_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "workflow": { + "name": "workflow", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "workflow_api": { + "name": "workflow_api", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "version": { + "name": "version", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "snapshot": { + "name": "snapshot", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "workflow_versions_workflow_id_workflows_id_fk": { + "name": "workflow_versions_workflow_id_workflows_id_fk", + "tableFrom": "workflow_versions", + "tableTo": "workflows", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + } + }, + "enums": { + "deployment_environment": { + "name": "deployment_environment", + "values": { + "staging": "staging", + "production": "production", + "public-share": "public-share" + } + }, + "machine_gpu": { + "name": "machine_gpu", + "values": { + "T4": "T4", + "A10G": "A10G", + "A100": "A100" + } + }, + "machine_status": { + "name": "machine_status", + "values": { + "ready": "ready", + "building": "building", + "error": "error" + } + }, + "machine_type": { + "name": "machine_type", + "values": { + "classic": "classic", + "runpod-serverless": "runpod-serverless", + "modal-serverless": "modal-serverless", + "comfy-deploy-serverless": "comfy-deploy-serverless" + } + }, + "subscription_plan": { + "name": "subscription_plan", + "values": { + "basic": "basic", + "pro": "pro", + "enterprise": "enterprise" + } + }, + "subscription_plan_status": { + "name": "subscription_plan_status", + "values": { + "active": "active", + "deleted": "deleted", + "paused": "paused" + } + }, + "workflow_run_origin": { + "name": "workflow_run_origin", + "values": { + "manual": "manual", + "api": "api", + "public-share": "public-share" + } + }, + "workflow_run_status": { + "name": "workflow_run_status", + "values": { + "not-started": "not-started", + "running": "running", + "uploading": "uploading", + "success": "success", + "failed": "failed" + } + } + }, + "schemas": { + "comfyui_deploy": "comfyui_deploy" + }, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": { + "\"comfyui_deploy\".\"subscription_status\".\"subscription_plan_id\"": "\"comfyui_deploy\".\"subscription_status\".\"subscription_id\"" + } + } +} \ No newline at end of file diff --git a/web/drizzle/meta/0038_snapshot.json b/web/drizzle/meta/0038_snapshot.json new file mode 100644 index 0000000..510c5e5 --- /dev/null +++ b/web/drizzle/meta/0038_snapshot.json @@ -0,0 +1,989 @@ +{ + "id": "bd893271-b9ea-4832-a3e8-a6970b9f20d9", + "prevId": "cde8f758-0055-4326-981d-293ac84db54a", + "version": "5", + "dialect": "pg", + "tables": { + "api_keys": { + "name": "api_keys", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "revoked": { + "name": "revoked", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "api_keys_user_id_users_id_fk": { + "name": "api_keys_user_id_users_id_fk", + "tableFrom": "api_keys", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "api_keys_key_unique": { + "name": "api_keys_key_unique", + "nullsNotDistinct": false, + "columns": [ + "key" + ] + } + } + }, + "auth_requests": { + "name": "auth_requests", + "schema": "comfyui_deploy", + "columns": { + "request_id": { + "name": "request_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "api_hash": { + "name": "api_hash", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expired_date": { + "name": "expired_date", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "deployments": { + "name": "deployments", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "workflow_version_id": { + "name": "workflow_version_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "machine_id": { + "name": "machine_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "share_slug": { + "name": "share_slug", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "showcase_media": { + "name": "showcase_media", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "environment": { + "name": "environment", + "type": "deployment_environment", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "deployments_user_id_users_id_fk": { + "name": "deployments_user_id_users_id_fk", + "tableFrom": "deployments", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "deployments_workflow_version_id_workflow_versions_id_fk": { + "name": "deployments_workflow_version_id_workflow_versions_id_fk", + "tableFrom": "deployments", + "tableTo": "workflow_versions", + "columnsFrom": [ + "workflow_version_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "deployments_workflow_id_workflows_id_fk": { + "name": "deployments_workflow_id_workflows_id_fk", + "tableFrom": "deployments", + "tableTo": "workflows", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "deployments_machine_id_machines_id_fk": { + "name": "deployments_machine_id_machines_id_fk", + "tableFrom": "deployments", + "tableTo": "machines", + "columnsFrom": [ + "machine_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "deployments_share_slug_unique": { + "name": "deployments_share_slug_unique", + "nullsNotDistinct": false, + "columns": [ + "share_slug" + ] + } + } + }, + "machines": { + "name": "machines", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "endpoint": { + "name": "endpoint", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "disabled": { + "name": "disabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "auth_token": { + "name": "auth_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "type": { + "name": "type", + "type": "machine_type", + "primaryKey": false, + "notNull": true, + "default": "'classic'" + }, + "status": { + "name": "status", + "type": "machine_status", + "primaryKey": false, + "notNull": true, + "default": "'ready'" + }, + "snapshot": { + "name": "snapshot", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "models": { + "name": "models", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "gpu": { + "name": "gpu", + "type": "machine_gpu", + "primaryKey": false, + "notNull": false + }, + "build_machine_instance_id": { + "name": "build_machine_instance_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "build_log": { + "name": "build_log", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "machines_user_id_users_id_fk": { + "name": "machines_user_id_users_id_fk", + "tableFrom": "machines", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "subscription_status": { + "name": "subscription_status", + "schema": "comfyui_deploy", + "columns": { + "stripe_customer_id": { + "name": "stripe_customer_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "plan": { + "name": "plan", + "type": "subscription_plan", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "subscription_plan_status", + "primaryKey": false, + "notNull": true + }, + "subscription_id": { + "name": "subscription_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "subscription_item_plan_id": { + "name": "subscription_item_plan_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "subscription_item_api_id": { + "name": "subscription_item_api_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cancel_at_period_end": { + "name": "cancel_at_period_end", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "user_usage": { + "name": "user_usage", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "usage_time": { + "name": "usage_time", + "type": "real", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "ended_at": { + "name": "ended_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "user_usage_user_id_users_id_fk": { + "name": "user_usage_user_id_users_id_fk", + "tableFrom": "user_usage", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "users": { + "name": "users", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "workflow_run_outputs": { + "name": "workflow_run_outputs", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "run_id": { + "name": "run_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "data": { + "name": "data", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "workflow_run_outputs_run_id_workflow_runs_id_fk": { + "name": "workflow_run_outputs_run_id_workflow_runs_id_fk", + "tableFrom": "workflow_run_outputs", + "tableTo": "workflow_runs", + "columnsFrom": [ + "run_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "workflow_runs": { + "name": "workflow_runs", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "workflow_version_id": { + "name": "workflow_version_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "workflow_inputs": { + "name": "workflow_inputs", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "workflow_id": { + "name": "workflow_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "machine_id": { + "name": "machine_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "origin": { + "name": "origin", + "type": "workflow_run_origin", + "primaryKey": false, + "notNull": true, + "default": "'api'" + }, + "status": { + "name": "status", + "type": "workflow_run_status", + "primaryKey": false, + "notNull": true, + "default": "'not-started'" + }, + "ended_at": { + "name": "ended_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "started_at": { + "name": "started_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "workflow_runs_workflow_version_id_workflow_versions_id_fk": { + "name": "workflow_runs_workflow_version_id_workflow_versions_id_fk", + "tableFrom": "workflow_runs", + "tableTo": "workflow_versions", + "columnsFrom": [ + "workflow_version_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "workflow_runs_workflow_id_workflows_id_fk": { + "name": "workflow_runs_workflow_id_workflows_id_fk", + "tableFrom": "workflow_runs", + "tableTo": "workflows", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_runs_machine_id_machines_id_fk": { + "name": "workflow_runs_machine_id_machines_id_fk", + "tableFrom": "workflow_runs", + "tableTo": "machines", + "columnsFrom": [ + "machine_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "workflows": { + "name": "workflows", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "workflows_user_id_users_id_fk": { + "name": "workflows_user_id_users_id_fk", + "tableFrom": "workflows", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "workflow_versions": { + "name": "workflow_versions", + "schema": "comfyui_deploy", + "columns": { + "workflow_id": { + "name": "workflow_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "workflow": { + "name": "workflow", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "workflow_api": { + "name": "workflow_api", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "version": { + "name": "version", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "snapshot": { + "name": "snapshot", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "workflow_versions_workflow_id_workflows_id_fk": { + "name": "workflow_versions_workflow_id_workflows_id_fk", + "tableFrom": "workflow_versions", + "tableTo": "workflows", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + } + }, + "enums": { + "deployment_environment": { + "name": "deployment_environment", + "values": { + "staging": "staging", + "production": "production", + "public-share": "public-share" + } + }, + "machine_gpu": { + "name": "machine_gpu", + "values": { + "T4": "T4", + "A10G": "A10G", + "A100": "A100" + } + }, + "machine_status": { + "name": "machine_status", + "values": { + "ready": "ready", + "building": "building", + "error": "error" + } + }, + "machine_type": { + "name": "machine_type", + "values": { + "classic": "classic", + "runpod-serverless": "runpod-serverless", + "modal-serverless": "modal-serverless", + "comfy-deploy-serverless": "comfy-deploy-serverless" + } + }, + "subscription_plan": { + "name": "subscription_plan", + "values": { + "basic": "basic", + "pro": "pro", + "enterprise": "enterprise" + } + }, + "subscription_plan_status": { + "name": "subscription_plan_status", + "values": { + "active": "active", + "deleted": "deleted", + "paused": "paused" + } + }, + "workflow_run_origin": { + "name": "workflow_run_origin", + "values": { + "manual": "manual", + "api": "api", + "public-share": "public-share" + } + }, + "workflow_run_status": { + "name": "workflow_run_status", + "values": { + "not-started": "not-started", + "running": "running", + "uploading": "uploading", + "success": "success", + "failed": "failed" + } + } + }, + "schemas": { + "comfyui_deploy": "comfyui_deploy" + }, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + } +} \ No newline at end of file diff --git a/web/drizzle/meta/0039_snapshot.json b/web/drizzle/meta/0039_snapshot.json new file mode 100644 index 0000000..b53aec6 --- /dev/null +++ b/web/drizzle/meta/0039_snapshot.json @@ -0,0 +1,1001 @@ +{ + "id": "b9a3bdfb-4187-4647-860e-1006b38b7497", + "prevId": "bd893271-b9ea-4832-a3e8-a6970b9f20d9", + "version": "5", + "dialect": "pg", + "tables": { + "api_keys": { + "name": "api_keys", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "revoked": { + "name": "revoked", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "api_keys_user_id_users_id_fk": { + "name": "api_keys_user_id_users_id_fk", + "tableFrom": "api_keys", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "api_keys_key_unique": { + "name": "api_keys_key_unique", + "nullsNotDistinct": false, + "columns": [ + "key" + ] + } + } + }, + "auth_requests": { + "name": "auth_requests", + "schema": "comfyui_deploy", + "columns": { + "request_id": { + "name": "request_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "api_hash": { + "name": "api_hash", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expired_date": { + "name": "expired_date", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "deployments": { + "name": "deployments", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "workflow_version_id": { + "name": "workflow_version_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "machine_id": { + "name": "machine_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "share_slug": { + "name": "share_slug", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "showcase_media": { + "name": "showcase_media", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "environment": { + "name": "environment", + "type": "deployment_environment", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "deployments_user_id_users_id_fk": { + "name": "deployments_user_id_users_id_fk", + "tableFrom": "deployments", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "deployments_workflow_version_id_workflow_versions_id_fk": { + "name": "deployments_workflow_version_id_workflow_versions_id_fk", + "tableFrom": "deployments", + "tableTo": "workflow_versions", + "columnsFrom": [ + "workflow_version_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "deployments_workflow_id_workflows_id_fk": { + "name": "deployments_workflow_id_workflows_id_fk", + "tableFrom": "deployments", + "tableTo": "workflows", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "deployments_machine_id_machines_id_fk": { + "name": "deployments_machine_id_machines_id_fk", + "tableFrom": "deployments", + "tableTo": "machines", + "columnsFrom": [ + "machine_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "deployments_share_slug_unique": { + "name": "deployments_share_slug_unique", + "nullsNotDistinct": false, + "columns": [ + "share_slug" + ] + } + } + }, + "machines": { + "name": "machines", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "endpoint": { + "name": "endpoint", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "disabled": { + "name": "disabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "auth_token": { + "name": "auth_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "type": { + "name": "type", + "type": "machine_type", + "primaryKey": false, + "notNull": true, + "default": "'classic'" + }, + "status": { + "name": "status", + "type": "machine_status", + "primaryKey": false, + "notNull": true, + "default": "'ready'" + }, + "snapshot": { + "name": "snapshot", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "models": { + "name": "models", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "gpu": { + "name": "gpu", + "type": "machine_gpu", + "primaryKey": false, + "notNull": false + }, + "build_machine_instance_id": { + "name": "build_machine_instance_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "build_log": { + "name": "build_log", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "machines_user_id_users_id_fk": { + "name": "machines_user_id_users_id_fk", + "tableFrom": "machines", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "subscription_status": { + "name": "subscription_status", + "schema": "comfyui_deploy", + "columns": { + "stripe_customer_id": { + "name": "stripe_customer_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "plan": { + "name": "plan", + "type": "subscription_plan", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "subscription_plan_status", + "primaryKey": false, + "notNull": true + }, + "subscription_id": { + "name": "subscription_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "subscription_item_plan_id": { + "name": "subscription_item_plan_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "subscription_item_api_id": { + "name": "subscription_item_api_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cancel_at_period_end": { + "name": "cancel_at_period_end", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "user_usage": { + "name": "user_usage", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "usage_time": { + "name": "usage_time", + "type": "real", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "ended_at": { + "name": "ended_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "user_usage_user_id_users_id_fk": { + "name": "user_usage_user_id_users_id_fk", + "tableFrom": "user_usage", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "users": { + "name": "users", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "workflow_run_outputs": { + "name": "workflow_run_outputs", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "run_id": { + "name": "run_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "data": { + "name": "data", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "workflow_run_outputs_run_id_workflow_runs_id_fk": { + "name": "workflow_run_outputs_run_id_workflow_runs_id_fk", + "tableFrom": "workflow_run_outputs", + "tableTo": "workflow_runs", + "columnsFrom": [ + "run_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "workflow_runs": { + "name": "workflow_runs", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "workflow_version_id": { + "name": "workflow_version_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "workflow_inputs": { + "name": "workflow_inputs", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "workflow_id": { + "name": "workflow_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "machine_id": { + "name": "machine_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "origin": { + "name": "origin", + "type": "workflow_run_origin", + "primaryKey": false, + "notNull": true, + "default": "'api'" + }, + "status": { + "name": "status", + "type": "workflow_run_status", + "primaryKey": false, + "notNull": true, + "default": "'not-started'" + }, + "ended_at": { + "name": "ended_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "started_at": { + "name": "started_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "workflow_runs_workflow_version_id_workflow_versions_id_fk": { + "name": "workflow_runs_workflow_version_id_workflow_versions_id_fk", + "tableFrom": "workflow_runs", + "tableTo": "workflow_versions", + "columnsFrom": [ + "workflow_version_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "workflow_runs_workflow_id_workflows_id_fk": { + "name": "workflow_runs_workflow_id_workflows_id_fk", + "tableFrom": "workflow_runs", + "tableTo": "workflows", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_runs_machine_id_machines_id_fk": { + "name": "workflow_runs_machine_id_machines_id_fk", + "tableFrom": "workflow_runs", + "tableTo": "machines", + "columnsFrom": [ + "machine_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "workflows": { + "name": "workflows", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "workflows_user_id_users_id_fk": { + "name": "workflows_user_id_users_id_fk", + "tableFrom": "workflows", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "workflow_versions": { + "name": "workflow_versions", + "schema": "comfyui_deploy", + "columns": { + "workflow_id": { + "name": "workflow_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "workflow": { + "name": "workflow", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "workflow_api": { + "name": "workflow_api", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "version": { + "name": "version", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "snapshot": { + "name": "snapshot", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "workflow_versions_workflow_id_workflows_id_fk": { + "name": "workflow_versions_workflow_id_workflows_id_fk", + "tableFrom": "workflow_versions", + "tableTo": "workflows", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + } + }, + "enums": { + "deployment_environment": { + "name": "deployment_environment", + "values": { + "staging": "staging", + "production": "production", + "public-share": "public-share" + } + }, + "machine_gpu": { + "name": "machine_gpu", + "values": { + "T4": "T4", + "A10G": "A10G", + "A100": "A100" + } + }, + "machine_status": { + "name": "machine_status", + "values": { + "ready": "ready", + "building": "building", + "error": "error" + } + }, + "machine_type": { + "name": "machine_type", + "values": { + "classic": "classic", + "runpod-serverless": "runpod-serverless", + "modal-serverless": "modal-serverless", + "comfy-deploy-serverless": "comfy-deploy-serverless" + } + }, + "subscription_plan": { + "name": "subscription_plan", + "values": { + "basic": "basic", + "pro": "pro", + "enterprise": "enterprise" + } + }, + "subscription_plan_status": { + "name": "subscription_plan_status", + "values": { + "active": "active", + "deleted": "deleted", + "paused": "paused" + } + }, + "workflow_run_origin": { + "name": "workflow_run_origin", + "values": { + "manual": "manual", + "api": "api", + "public-share": "public-share" + } + }, + "workflow_run_status": { + "name": "workflow_run_status", + "values": { + "not-started": "not-started", + "running": "running", + "uploading": "uploading", + "success": "success", + "failed": "failed" + } + } + }, + "schemas": { + "comfyui_deploy": "comfyui_deploy" + }, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + } +} \ No newline at end of file diff --git a/web/drizzle/meta/0040_snapshot.json b/web/drizzle/meta/0040_snapshot.json new file mode 100644 index 0000000..2ad2884 --- /dev/null +++ b/web/drizzle/meta/0040_snapshot.json @@ -0,0 +1,1007 @@ +{ + "id": "f9f2dcab-1196-42db-bd79-872d2784c8b9", + "prevId": "b9a3bdfb-4187-4647-860e-1006b38b7497", + "version": "5", + "dialect": "pg", + "tables": { + "api_keys": { + "name": "api_keys", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "revoked": { + "name": "revoked", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "api_keys_user_id_users_id_fk": { + "name": "api_keys_user_id_users_id_fk", + "tableFrom": "api_keys", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "api_keys_key_unique": { + "name": "api_keys_key_unique", + "nullsNotDistinct": false, + "columns": [ + "key" + ] + } + } + }, + "auth_requests": { + "name": "auth_requests", + "schema": "comfyui_deploy", + "columns": { + "request_id": { + "name": "request_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "api_hash": { + "name": "api_hash", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expired_date": { + "name": "expired_date", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "deployments": { + "name": "deployments", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "workflow_version_id": { + "name": "workflow_version_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "machine_id": { + "name": "machine_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "share_slug": { + "name": "share_slug", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "showcase_media": { + "name": "showcase_media", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "environment": { + "name": "environment", + "type": "deployment_environment", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "deployments_user_id_users_id_fk": { + "name": "deployments_user_id_users_id_fk", + "tableFrom": "deployments", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "deployments_workflow_version_id_workflow_versions_id_fk": { + "name": "deployments_workflow_version_id_workflow_versions_id_fk", + "tableFrom": "deployments", + "tableTo": "workflow_versions", + "columnsFrom": [ + "workflow_version_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "deployments_workflow_id_workflows_id_fk": { + "name": "deployments_workflow_id_workflows_id_fk", + "tableFrom": "deployments", + "tableTo": "workflows", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "deployments_machine_id_machines_id_fk": { + "name": "deployments_machine_id_machines_id_fk", + "tableFrom": "deployments", + "tableTo": "machines", + "columnsFrom": [ + "machine_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "deployments_share_slug_unique": { + "name": "deployments_share_slug_unique", + "nullsNotDistinct": false, + "columns": [ + "share_slug" + ] + } + } + }, + "machines": { + "name": "machines", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "endpoint": { + "name": "endpoint", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "disabled": { + "name": "disabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "auth_token": { + "name": "auth_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "type": { + "name": "type", + "type": "machine_type", + "primaryKey": false, + "notNull": true, + "default": "'classic'" + }, + "status": { + "name": "status", + "type": "machine_status", + "primaryKey": false, + "notNull": true, + "default": "'ready'" + }, + "snapshot": { + "name": "snapshot", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "models": { + "name": "models", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "gpu": { + "name": "gpu", + "type": "machine_gpu", + "primaryKey": false, + "notNull": false + }, + "build_machine_instance_id": { + "name": "build_machine_instance_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "build_log": { + "name": "build_log", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "machines_user_id_users_id_fk": { + "name": "machines_user_id_users_id_fk", + "tableFrom": "machines", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "subscription_status": { + "name": "subscription_status", + "schema": "comfyui_deploy", + "columns": { + "stripe_customer_id": { + "name": "stripe_customer_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "plan": { + "name": "plan", + "type": "subscription_plan", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "subscription_plan_status", + "primaryKey": false, + "notNull": true + }, + "subscription_id": { + "name": "subscription_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "subscription_item_plan_id": { + "name": "subscription_item_plan_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "subscription_item_api_id": { + "name": "subscription_item_api_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cancel_at_period_end": { + "name": "cancel_at_period_end", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "user_usage": { + "name": "user_usage", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "usage_time": { + "name": "usage_time", + "type": "real", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "ended_at": { + "name": "ended_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "user_usage_user_id_users_id_fk": { + "name": "user_usage_user_id_users_id_fk", + "tableFrom": "user_usage", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "users": { + "name": "users", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "workflow_run_outputs": { + "name": "workflow_run_outputs", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "run_id": { + "name": "run_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "data": { + "name": "data", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "workflow_run_outputs_run_id_workflow_runs_id_fk": { + "name": "workflow_run_outputs_run_id_workflow_runs_id_fk", + "tableFrom": "workflow_run_outputs", + "tableTo": "workflow_runs", + "columnsFrom": [ + "run_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "workflow_runs": { + "name": "workflow_runs", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "workflow_version_id": { + "name": "workflow_version_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "workflow_inputs": { + "name": "workflow_inputs", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "workflow_id": { + "name": "workflow_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "machine_id": { + "name": "machine_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "origin": { + "name": "origin", + "type": "workflow_run_origin", + "primaryKey": false, + "notNull": true, + "default": "'api'" + }, + "status": { + "name": "status", + "type": "workflow_run_status", + "primaryKey": false, + "notNull": true, + "default": "'not-started'" + }, + "ended_at": { + "name": "ended_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "started_at": { + "name": "started_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "gpu": { + "name": "gpu", + "type": "machine_gpu", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "workflow_runs_workflow_version_id_workflow_versions_id_fk": { + "name": "workflow_runs_workflow_version_id_workflow_versions_id_fk", + "tableFrom": "workflow_runs", + "tableTo": "workflow_versions", + "columnsFrom": [ + "workflow_version_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "workflow_runs_workflow_id_workflows_id_fk": { + "name": "workflow_runs_workflow_id_workflows_id_fk", + "tableFrom": "workflow_runs", + "tableTo": "workflows", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_runs_machine_id_machines_id_fk": { + "name": "workflow_runs_machine_id_machines_id_fk", + "tableFrom": "workflow_runs", + "tableTo": "machines", + "columnsFrom": [ + "machine_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "workflows": { + "name": "workflows", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "workflows_user_id_users_id_fk": { + "name": "workflows_user_id_users_id_fk", + "tableFrom": "workflows", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "workflow_versions": { + "name": "workflow_versions", + "schema": "comfyui_deploy", + "columns": { + "workflow_id": { + "name": "workflow_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "workflow": { + "name": "workflow", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "workflow_api": { + "name": "workflow_api", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "version": { + "name": "version", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "snapshot": { + "name": "snapshot", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "workflow_versions_workflow_id_workflows_id_fk": { + "name": "workflow_versions_workflow_id_workflows_id_fk", + "tableFrom": "workflow_versions", + "tableTo": "workflows", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + } + }, + "enums": { + "deployment_environment": { + "name": "deployment_environment", + "values": { + "staging": "staging", + "production": "production", + "public-share": "public-share" + } + }, + "machine_gpu": { + "name": "machine_gpu", + "values": { + "T4": "T4", + "A10G": "A10G", + "A100": "A100" + } + }, + "machine_status": { + "name": "machine_status", + "values": { + "ready": "ready", + "building": "building", + "error": "error" + } + }, + "machine_type": { + "name": "machine_type", + "values": { + "classic": "classic", + "runpod-serverless": "runpod-serverless", + "modal-serverless": "modal-serverless", + "comfy-deploy-serverless": "comfy-deploy-serverless" + } + }, + "subscription_plan": { + "name": "subscription_plan", + "values": { + "basic": "basic", + "pro": "pro", + "enterprise": "enterprise" + } + }, + "subscription_plan_status": { + "name": "subscription_plan_status", + "values": { + "active": "active", + "deleted": "deleted", + "paused": "paused" + } + }, + "workflow_run_origin": { + "name": "workflow_run_origin", + "values": { + "manual": "manual", + "api": "api", + "public-share": "public-share" + } + }, + "workflow_run_status": { + "name": "workflow_run_status", + "values": { + "not-started": "not-started", + "running": "running", + "uploading": "uploading", + "success": "success", + "failed": "failed" + } + } + }, + "schemas": { + "comfyui_deploy": "comfyui_deploy" + }, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + } +} \ No newline at end of file diff --git a/web/drizzle/meta/0041_snapshot.json b/web/drizzle/meta/0041_snapshot.json new file mode 100644 index 0000000..10b8023 --- /dev/null +++ b/web/drizzle/meta/0041_snapshot.json @@ -0,0 +1,1013 @@ +{ + "id": "ca1ab9de-49df-4d4a-81ae-d3db96bf55ad", + "prevId": "f9f2dcab-1196-42db-bd79-872d2784c8b9", + "version": "5", + "dialect": "pg", + "tables": { + "api_keys": { + "name": "api_keys", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "revoked": { + "name": "revoked", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "api_keys_user_id_users_id_fk": { + "name": "api_keys_user_id_users_id_fk", + "tableFrom": "api_keys", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "api_keys_key_unique": { + "name": "api_keys_key_unique", + "nullsNotDistinct": false, + "columns": [ + "key" + ] + } + } + }, + "auth_requests": { + "name": "auth_requests", + "schema": "comfyui_deploy", + "columns": { + "request_id": { + "name": "request_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "api_hash": { + "name": "api_hash", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expired_date": { + "name": "expired_date", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "deployments": { + "name": "deployments", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "workflow_version_id": { + "name": "workflow_version_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "machine_id": { + "name": "machine_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "share_slug": { + "name": "share_slug", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "showcase_media": { + "name": "showcase_media", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "environment": { + "name": "environment", + "type": "deployment_environment", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "deployments_user_id_users_id_fk": { + "name": "deployments_user_id_users_id_fk", + "tableFrom": "deployments", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "deployments_workflow_version_id_workflow_versions_id_fk": { + "name": "deployments_workflow_version_id_workflow_versions_id_fk", + "tableFrom": "deployments", + "tableTo": "workflow_versions", + "columnsFrom": [ + "workflow_version_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "deployments_workflow_id_workflows_id_fk": { + "name": "deployments_workflow_id_workflows_id_fk", + "tableFrom": "deployments", + "tableTo": "workflows", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "deployments_machine_id_machines_id_fk": { + "name": "deployments_machine_id_machines_id_fk", + "tableFrom": "deployments", + "tableTo": "machines", + "columnsFrom": [ + "machine_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "deployments_share_slug_unique": { + "name": "deployments_share_slug_unique", + "nullsNotDistinct": false, + "columns": [ + "share_slug" + ] + } + } + }, + "machines": { + "name": "machines", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "endpoint": { + "name": "endpoint", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "disabled": { + "name": "disabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "auth_token": { + "name": "auth_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "type": { + "name": "type", + "type": "machine_type", + "primaryKey": false, + "notNull": true, + "default": "'classic'" + }, + "status": { + "name": "status", + "type": "machine_status", + "primaryKey": false, + "notNull": true, + "default": "'ready'" + }, + "snapshot": { + "name": "snapshot", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "models": { + "name": "models", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "gpu": { + "name": "gpu", + "type": "machine_gpu", + "primaryKey": false, + "notNull": false + }, + "build_machine_instance_id": { + "name": "build_machine_instance_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "build_log": { + "name": "build_log", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "machines_user_id_users_id_fk": { + "name": "machines_user_id_users_id_fk", + "tableFrom": "machines", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "subscription_status": { + "name": "subscription_status", + "schema": "comfyui_deploy", + "columns": { + "stripe_customer_id": { + "name": "stripe_customer_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "plan": { + "name": "plan", + "type": "subscription_plan", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "subscription_plan_status", + "primaryKey": false, + "notNull": true + }, + "subscription_id": { + "name": "subscription_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "subscription_item_plan_id": { + "name": "subscription_item_plan_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "subscription_item_api_id": { + "name": "subscription_item_api_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cancel_at_period_end": { + "name": "cancel_at_period_end", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "user_usage": { + "name": "user_usage", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "usage_time": { + "name": "usage_time", + "type": "real", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "ended_at": { + "name": "ended_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "user_usage_user_id_users_id_fk": { + "name": "user_usage_user_id_users_id_fk", + "tableFrom": "user_usage", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "users": { + "name": "users", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "workflow_run_outputs": { + "name": "workflow_run_outputs", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "run_id": { + "name": "run_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "data": { + "name": "data", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "workflow_run_outputs_run_id_workflow_runs_id_fk": { + "name": "workflow_run_outputs_run_id_workflow_runs_id_fk", + "tableFrom": "workflow_run_outputs", + "tableTo": "workflow_runs", + "columnsFrom": [ + "run_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "workflow_runs": { + "name": "workflow_runs", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "workflow_version_id": { + "name": "workflow_version_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "workflow_inputs": { + "name": "workflow_inputs", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "workflow_id": { + "name": "workflow_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "machine_id": { + "name": "machine_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "origin": { + "name": "origin", + "type": "workflow_run_origin", + "primaryKey": false, + "notNull": true, + "default": "'api'" + }, + "status": { + "name": "status", + "type": "workflow_run_status", + "primaryKey": false, + "notNull": true, + "default": "'not-started'" + }, + "ended_at": { + "name": "ended_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "started_at": { + "name": "started_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "gpu": { + "name": "gpu", + "type": "machine_gpu", + "primaryKey": false, + "notNull": false + }, + "machine_type": { + "name": "machine_type", + "type": "machine_type", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "workflow_runs_workflow_version_id_workflow_versions_id_fk": { + "name": "workflow_runs_workflow_version_id_workflow_versions_id_fk", + "tableFrom": "workflow_runs", + "tableTo": "workflow_versions", + "columnsFrom": [ + "workflow_version_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "workflow_runs_workflow_id_workflows_id_fk": { + "name": "workflow_runs_workflow_id_workflows_id_fk", + "tableFrom": "workflow_runs", + "tableTo": "workflows", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_runs_machine_id_machines_id_fk": { + "name": "workflow_runs_machine_id_machines_id_fk", + "tableFrom": "workflow_runs", + "tableTo": "machines", + "columnsFrom": [ + "machine_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "workflows": { + "name": "workflows", + "schema": "comfyui_deploy", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "org_id": { + "name": "org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "workflows_user_id_users_id_fk": { + "name": "workflows_user_id_users_id_fk", + "tableFrom": "workflows", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "workflow_versions": { + "name": "workflow_versions", + "schema": "comfyui_deploy", + "columns": { + "workflow_id": { + "name": "workflow_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "workflow": { + "name": "workflow", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "workflow_api": { + "name": "workflow_api", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "version": { + "name": "version", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "snapshot": { + "name": "snapshot", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "workflow_versions_workflow_id_workflows_id_fk": { + "name": "workflow_versions_workflow_id_workflows_id_fk", + "tableFrom": "workflow_versions", + "tableTo": "workflows", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + } + }, + "enums": { + "deployment_environment": { + "name": "deployment_environment", + "values": { + "staging": "staging", + "production": "production", + "public-share": "public-share" + } + }, + "machine_gpu": { + "name": "machine_gpu", + "values": { + "T4": "T4", + "A10G": "A10G", + "A100": "A100" + } + }, + "machine_status": { + "name": "machine_status", + "values": { + "ready": "ready", + "building": "building", + "error": "error" + } + }, + "machine_type": { + "name": "machine_type", + "values": { + "classic": "classic", + "runpod-serverless": "runpod-serverless", + "modal-serverless": "modal-serverless", + "comfy-deploy-serverless": "comfy-deploy-serverless" + } + }, + "subscription_plan": { + "name": "subscription_plan", + "values": { + "basic": "basic", + "pro": "pro", + "enterprise": "enterprise" + } + }, + "subscription_plan_status": { + "name": "subscription_plan_status", + "values": { + "active": "active", + "deleted": "deleted", + "paused": "paused" + } + }, + "workflow_run_origin": { + "name": "workflow_run_origin", + "values": { + "manual": "manual", + "api": "api", + "public-share": "public-share" + } + }, + "workflow_run_status": { + "name": "workflow_run_status", + "values": { + "not-started": "not-started", + "running": "running", + "uploading": "uploading", + "success": "success", + "failed": "failed" + } + } + }, + "schemas": { + "comfyui_deploy": "comfyui_deploy" + }, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + } +} \ No newline at end of file diff --git a/web/drizzle/meta/_journal.json b/web/drizzle/meta/_journal.json index 69f5c17..60056be 100644 --- a/web/drizzle/meta/_journal.json +++ b/web/drizzle/meta/_journal.json @@ -246,6 +246,55 @@ "when": 1705902960991, "tag": "0034_even_lady_ursula", "breakpoints": true + }, + { + "idx": 35, + "version": "5", + "when": 1705981452482, + "tag": "0035_fearless_golden_guardian", + "breakpoints": true + }, + { + "idx": 36, + "version": "5", + "when": 1706081335387, + "tag": "0036_flippant_meltdown", + "breakpoints": true + }, + { + "idx": 37, + "version": "5", + "when": 1706086271525, + "tag": "0037_eager_cyclops", + "breakpoints": true + }, + { + "idx": 38, + "version": "5", + "when": 1706095853896, + "tag": "0038_yummy_darkhawk", + "breakpoints": true + }, + { + "idx": 39, + "version": "5", + "when": 1706109812261, + "tag": "0039_nostalgic_lyja", + "breakpoints": true + }, + { + "idx": 40, + "version": "5", + "when": 1706110859352, + "tag": "0040_salty_archangel", + "breakpoints": true + }, + { + "idx": 41, + "version": "5", + "when": 1706111421524, + "tag": "0041_thick_norrin_radd", + "breakpoints": true } ] -} +} \ No newline at end of file diff --git a/web/package.json b/web/package.json index c5625d3..717b26d 100644 --- a/web/package.json +++ b/web/package.json @@ -37,6 +37,7 @@ "@radix-ui/react-dropdown-menu": "^2.0.6", "@radix-ui/react-label": "^2.0.2", "@radix-ui/react-popover": "^1.0.7", + "@radix-ui/react-progress": "^1.0.3", "@radix-ui/react-radio-group": "^1.1.3", "@radix-ui/react-scroll-area": "^1.0.5", "@radix-ui/react-select": "^2.0.0", @@ -47,6 +48,7 @@ "@radix-ui/react-toggle": "^1.0.3", "@radix-ui/react-tooltip": "^1.0.7", "@sindresorhus/slugify": "^2.2.1", + "@stripe/stripe-js": "^2.4.0", "@tailwindcss/typography": "^0.5.10", "@tanstack/react-table": "^8.10.7", "@tanstack/react-virtual": "beta", @@ -95,6 +97,7 @@ "shikiji": "^0.9.3", "simple-functional-loader": "^1.2.1", "sonner": "^1.2.4", + "stripe": "^14.13.0", "swagger-ui-react": "^5.11.0", "swr": "^2.2.4", "tailwind-merge": "^2.1.0", diff --git a/web/src/app/(app)/api/stripe/callback/route.tsx b/web/src/app/(app)/api/stripe/callback/route.tsx new file mode 100644 index 0000000..7eec55e --- /dev/null +++ b/web/src/app/(app)/api/stripe/callback/route.tsx @@ -0,0 +1,175 @@ +import { auth, clerkClient } from "@clerk/nextjs"; +import { headers } from "next/headers"; +import { redirect } from "next/navigation"; +import { stripe } from "../../../../../server/stripe"; +import { NextResponse } from "next/server"; +import { db } from "@/db/db"; +import { subscriptionStatusTable } from "@/db/schema"; +import { eq } from "drizzle-orm"; + +const secret = process.env.STRIPE_WEBHOOK_SECRET || ""; + +export async function POST(req: Request) { + try { + const body = await req.text(); + + const signature = headers().get("stripe-signature"); + + if (!signature) + return new NextResponse("Signature not found.", { + status: 500, + }); + + const event = stripe.webhooks.constructEvent(body, signature, secret); + + console.log(event); + + if (event.type === "checkout.session.completed") { + if (!event.data.object.customer_details?.email) { + throw new Error(`missing user email, ${event.id}`); + } + + const userId = event.data.object.metadata?.userId; + const plan = event.data.object.metadata?.plan; + if (!userId) { + throw new Error(`missing itinerary_id on metadata, ${event.id}`); + } + if (!plan) { + throw new Error(`missing plan on metadata, ${event.id}`); + } + + const orgId = event.data.object.metadata?.orgId; + + const customerId = + typeof event.data.object.customer == "string" + ? event.data.object.customer + : event.data.object.customer?.id; + const subscriptionId = + typeof event.data.object.subscription == "string" + ? event.data.object.subscription + : event.data.object.subscription?.id; + + if (!customerId) { + throw new Error(`missing customerId, ${event.id}`); + } + if (!subscriptionId) { + throw new Error(`missing subscriptionId, ${event.id}`); + } + + const items = await stripe.subscriptionItems.list({ + subscription: subscriptionId, + limit: 5, + }); + + // getting the subscription item id for the api plan + const subscription_item_api_id = items.data.find( + (x) => x.price.id === process.env.STRIPE_PR_API, + )?.id; + + // the plan could be either pro or enterprise + const subscription_item_plan_id = + items.data.find((x) => x.price.id === process.env.STRIPE_PR_PRO)?.id ?? + items.data.find((x) => x.price.id === process.env.STRIPE_PR_ENTERPRISE) + ?.id; + + if (!subscription_item_api_id) { + throw new Error( + `missing plan on subscription_item_api_id, ${event.id}`, + ); + } + if (!subscription_item_plan_id) { + throw new Error( + `missing plan on subscription_item_plan_id, ${event.id}`, + ); + } + + console.log(items); + + await db + .insert(subscriptionStatusTable) + .values({ + stripe_customer_id: customerId, + org_id: orgId, + user_id: userId, + subscription_id: subscriptionId, + plan: plan as "pro" | "enterprise" | "basic", + status: "active", + subscription_item_api_id: subscription_item_api_id, + subscription_item_plan_id: subscription_item_plan_id, + }) + .onConflictDoNothing(); + + // updateDatabase(event.data.object.metadata.itinerary_id); + // sendEmail(event.data.object.customer_details.email); + } else if (event.type === "customer.subscription.paused") { + const customerId = + typeof event.data.object.customer == "string" + ? event.data.object.customer + : event.data.object.customer?.id; + + if (!customerId) { + throw new Error(`missing customerId, ${event.id}`); + } + + await db + .update(subscriptionStatusTable) + .set({ status: "paused" }) + .where(eq(subscriptionStatusTable.stripe_customer_id, customerId)); + } else if (event.type === "customer.subscription.resumed") { + const customerId = + typeof event.data.object.customer == "string" + ? event.data.object.customer + : event.data.object.customer?.id; + + if (!customerId) { + throw new Error(`missing customerId, ${event.id}`); + } + + await db + .update(subscriptionStatusTable) + .set({ status: "active" }) + .where(eq(subscriptionStatusTable.stripe_customer_id, customerId)); + } else if (event.type === "customer.subscription.deleted") { + const customerId = + typeof event.data.object.customer == "string" + ? event.data.object.customer + : event.data.object.customer?.id; + + if (!customerId) { + throw new Error(`missing customerId, ${event.id}`); + } + + await db + .update(subscriptionStatusTable) + .set({ status: "deleted" }) + .where(eq(subscriptionStatusTable.stripe_customer_id, customerId)); + } else if (event.type === "customer.subscription.updated") { + const customerId = + typeof event.data.object.customer == "string" + ? event.data.object.customer + : event.data.object.customer?.id; + + if (!customerId) { + throw new Error(`missing customerId, ${event.id}`); + } + + const cancel_at_period_end = event.data.object.cancel_at_period_end; + + await db + .update(subscriptionStatusTable) + .set({ cancel_at_period_end: cancel_at_period_end }) + .where(eq(subscriptionStatusTable.stripe_customer_id, customerId)); + } + + return NextResponse.json({ result: event, ok: true }); + } catch (error) { + console.error(error); + return NextResponse.json( + { + message: `Something went wrong: ${error}`, + ok: false, + }, + { status: 500 }, + ); + } +} diff --git a/web/src/app/(app)/api/stripe/checkout/route.tsx b/web/src/app/(app)/api/stripe/checkout/route.tsx new file mode 100644 index 0000000..9ccd287 --- /dev/null +++ b/web/src/app/(app)/api/stripe/checkout/route.tsx @@ -0,0 +1,46 @@ +import { stripe } from "@/server/stripe"; +import { createCheckout } from "@/server/linkToPricing"; +import { auth, clerkClient } from "@clerk/nextjs"; +import { redirect } from "next/navigation"; +import { getUrlServerSide } from "@/server/getUrlServerSide"; + +export async function GET(req: Request) { + const { userId, orgId } = auth(); + + const plan = new URL(req.url).searchParams.get("plan"); + + if (!userId) return redirect("/"); + if (!plan) return redirect("/pricing"); + + const user = await clerkClient.users.getUser(userId); + + const mapping = { + pro: process.env.STRIPE_PR_PRO, + enterprise: process.env.STRIPE_PR_ENTERPRISE, + }; + + const api = process.env.STRIPE_PR_API; + + const session = await stripe.checkout.sessions.create({ + success_url: getUrlServerSide(), + line_items: [ + { + price: mapping[plan as "pro" | "enterprise"], + quantity: 1, + }, + { + price: api, + }, + ], + metadata: { + userId: userId, + orgId: orgId ?? null, + plan: plan, + }, + client_reference_id: orgId ?? userId, + customer_email: user.emailAddresses[0].emailAddress, + mode: "subscription", + }); + + if (session.url) redirect(session.url); +} diff --git a/web/src/app/(app)/api/stripe/dashboard/route.tsx b/web/src/app/(app)/api/stripe/dashboard/route.tsx new file mode 100644 index 0000000..95fe442 --- /dev/null +++ b/web/src/app/(app)/api/stripe/dashboard/route.tsx @@ -0,0 +1,41 @@ +import { stripe } from "@/server/stripe"; +import { createCheckout } from "@/server/linkToPricing"; +import { auth, clerkClient } from "@clerk/nextjs"; +import { redirect } from "next/navigation"; +import { getUrlServerSide } from "@/server/getUrlServerSide"; +import { db } from "@/db/db"; +import { and, eq, isNull } from "drizzle-orm"; +import { subscriptionStatusTable } from "@/db/schema"; +import { getCurrentPlan } from "@/server/getCurrentPlan"; + +export async function GET(req: Request) { + const { userId, orgId } = auth(); + + if (!userId) return redirect("/"); + + const change = new URL(req.url).searchParams.get("change"); + + const sub = await getCurrentPlan({ + org_id: orgId, + user_id: userId, + }); + + if (!sub) return redirect("/pricing"); + + const session = await stripe.billingPortal.sessions.create({ + customer: sub.stripe_customer_id, + return_url: getUrlServerSide() + "/pricing", + // flow_data: + // change === "true" && sub.subscription_id + // ? { + // type: "subscription_update", + // subscription_update: { + // subscription: sub.subscription_id, + // }, + // } + // : undefined, + }); + + redirect(session.url); + // if (session.url) redirect(session.url); +} diff --git a/web/src/app/(app)/api/update-run/route.ts b/web/src/app/(app)/api/update-run/route.ts index e4b98db..00dc35d 100644 --- a/web/src/app/(app)/api/update-run/route.ts +++ b/web/src/app/(app)/api/update-run/route.ts @@ -6,8 +6,8 @@ import { workflowRunsTable, workflowTable, } from "@/db/schema"; -import { getDuration } from "@/lib/getRelativeTime"; -import { getSubscription, setUsage } from "@/server/linkToPricing"; +import { getCurrentPlan } from "@/server/getCurrentPlan"; +import { stripe } from "@/server/stripe"; import { eq } from "drizzle-orm"; import { NextResponse } from "next/server"; import { z } from "zod"; @@ -34,21 +34,51 @@ export async function POST(request: Request) { data: output_data, }); } else if (status) { - const workflow_run = await db + const [workflow_run] = await db .update(workflowRunsTable) .set({ status: status, ended_at: status === "success" || status === "failed" ? new Date() : null, }) - .where(eq(workflowRunsTable.id, run_id)); + .where(eq(workflowRunsTable.id, run_id)) + .returning(); - // get data from workflowRunsTable - const userUsageTime = await importUserUsageData(run_id); + // Need to filter out only comfy deploy serverless + // Also multiply with the gpu selection + if (workflow_run.machine_type == "comfy-deploy-serverless") { + if ( + (status === "success" || status === "failed") && + workflow_run.user_id + ) { + const sub = await getCurrentPlan({ + user_id: workflow_run.user_id, + org_id: workflow_run.org_id, + }); - if (userUsageTime) { - // get the usage_time from userUsage - await addSubscriptionUnit(userUsageTime); + if (sub && sub.subscription_item_api_id && workflow_run.ended_at) { + let durationInSec = Math.abs( + (workflow_run.ended_at.getTime() - + workflow_run.created_at.getTime()) / + 1000, + ); + durationInSec = Math.ceil(durationInSec); + switch (workflow_run.gpu) { + case "A100": + durationInSec *= 7; + break; + case "A10G": + durationInSec *= 4; + break; + } + await stripe.subscriptionItems.createUsageRecord( + sub.subscription_item_api_id, + { + quantity: durationInSec, + }, + ); + } + } } } @@ -64,50 +94,6 @@ export async function POST(request: Request) { }, { status: 200, - } + }, ); } - -async function addSubscriptionUnit(userUsageTime: number) { - const subscription = await getSubscription(); - - // round up userUsageTime to the nearest integer - const roundedUsageTime = Math.ceil(userUsageTime); - - if (subscription) { - const usage = await setUsage( - subscription.data[0].attributes.first_subscription_item.id, - roundedUsageTime - ); - } -} - -async function importUserUsageData(run_id: string) { - const workflowRuns = await db.query.workflowRunsTable.findFirst({ - where: eq(workflowRunsTable.id, run_id), - }); - - if (!workflowRuns?.workflow_id) return; - - // find if workflowTable id column contains workflowRunsTable workflow_id - const workflow = await db.query.workflowTable.findFirst({ - where: eq(workflowTable.id, workflowRuns.workflow_id), - }); - - if (workflowRuns?.ended_at === null || workflow == null) return; - - const usageTime = parseFloat( - getDuration((workflowRuns?.ended_at - workflowRuns?.started_at) / 1000) - ); - - // add data to userUsageTable - const user_usage = await db.insert(userUsageTable).values({ - user_id: workflow.user_id, - created_at: workflowRuns.ended_at, - org_id: workflow.org_id, - ended_at: workflowRuns.ended_at, - usage_time: usageTime, - }); - - return usageTime; -} diff --git a/web/src/app/(app)/pricing/components/gpuPricingTable.tsx b/web/src/app/(app)/pricing/components/gpuPricingTable.tsx deleted file mode 100644 index 912f099..0000000 --- a/web/src/app/(app)/pricing/components/gpuPricingTable.tsx +++ /dev/null @@ -1,81 +0,0 @@ -const people = [ - { - name: "Nvidia T4 GPU", - gpu: "1x", - ram: "16GB", - price: "$0.000225/sec", - }, - { - name: "Nvidia A40 GPU", - gpu: "1x", - ram: "48GB", - price: "$0.000575/sec", - }, -]; - -export function GpuPricingPlan() { - return ( -
-
- - - - - - - - - - - {people.map((person) => ( - - - - - - - ))} - -
- GPU - - No. - - RAM - - Price -
- {person.name} -
-
No.
-
- {person.gpu} -
-
RAM
-
- {person.ram} -
-
-
- {person.gpu} - - {person.ram} - - {person.price} -
-
-
- ); -} diff --git a/web/src/app/(app)/pricing/components/pricePlanList.tsx b/web/src/app/(app)/pricing/components/pricePlanList.tsx deleted file mode 100644 index 89f4358..0000000 --- a/web/src/app/(app)/pricing/components/pricePlanList.tsx +++ /dev/null @@ -1,157 +0,0 @@ -import { checkMarkIcon, crossMarkIcon } from "../const/Icon"; -import { cn } from "@/lib/utils"; -import { getPricing } from "@/server/linkToPricing"; -import { useEffect, useState } from "react"; - -type Tier = { - name: string; - id: string; - href: string; - priceMonthly: string; - description: string; - features: string[]; - featured: boolean; - priority?: TierPriority; -}; - -enum TierPriority { - Free = "free", - Pro = "pro", - Enterprise = "enterprise", -} - -export default function PricingList() { - const [productTiers, setProductTiers] = useState(); - - useEffect(() => { - (async () => { - const product = await getPricing(); - - if (!product) return; - - const newProductTiers: Tier[] = product.data.map((item) => { - // Create a new DOMParser instance - const parser = new DOMParser(); - // Parse the description HTML string to a new document - const doc = parser.parseFromString( - item.attributes.description, - "text/html" - ); - // Extract the description and features - const description = doc.querySelector("p")?.textContent || ""; - const features = Array.from(doc.querySelectorAll("ul > li")).map( - (li) => li.textContent || "" - ); - - return { - name: item.attributes.name, - id: item.id, - href: item.attributes.buy_now_url, - priceMonthly: - item.attributes.price_formatted.split("/")[0] == "Usage-based" - ? "$20.00" - : item.attributes.price_formatted.split("/")[0], - description: description, - features: features, - - // if name contains pro, it's featured - featured: item.attributes.name.toLowerCase().includes("pro"), - - // give priority if name contain in enum - priority: Object.values(TierPriority).find((priority) => - item.attributes.name.toLowerCase().includes(priority) - ), - }; - }); - - // sort newProductTiers by priority - newProductTiers.sort((a, b) => { - if (!a.priority) return 1; - if (!b.priority) return -1; - return ( - Object.values(TierPriority).indexOf(a.priority) - - Object.values(TierPriority).indexOf(b.priority) - ); - }); - - setProductTiers(newProductTiers); - })(); - }, []); - - return ( -
-
-

- Pricing -

-

- The right price for you, whoever you are -

-
-

- Qui iusto aut est earum eos quae. Eligendi est at nam aliquid ad quo - reprehenderit in aliquid fugiat dolorum voluptatibus. -

-
- {productTiers && - productTiers.map((tier, tierIdx) => ( -
-

- {tier.name} -

-

- - {tier.priceMonthly} - - /month -

-

- {tier.description} -

-
    - {tier.features.map((feature) => ( -
  • -
    - {feature.includes("[x]") ? crossMarkIcon : checkMarkIcon} -
    - {feature.replace("[x]", "")} -
  • - ))} -
- - Get started today - -
- ))} -
-
- ); -} diff --git a/web/src/app/(app)/pricing/const/Icon.tsx b/web/src/app/(app)/pricing/const/Icon.tsx deleted file mode 100644 index 2257aee..0000000 --- a/web/src/app/(app)/pricing/const/Icon.tsx +++ /dev/null @@ -1,37 +0,0 @@ -export const checkMarkIcon = ( - -); - -export const crossMarkIcon = ( - - - - -); diff --git a/web/src/app/(app)/pricing/page.tsx b/web/src/app/(app)/pricing/page.tsx index fd94f22..c417b1a 100644 --- a/web/src/app/(app)/pricing/page.tsx +++ b/web/src/app/(app)/pricing/page.tsx @@ -1,13 +1,9 @@ -"use client"; - -import { GpuPricingPlan } from "@/app/(app)/pricing/components/gpuPricingTable"; -import PricingList from "@/app/(app)/pricing/components/pricePlanList"; +import PricingList from "@/components/PricingPlan"; export default function Home() { return (
-
); } diff --git a/web/src/app/(app)/providers.tsx b/web/src/app/(app)/providers.tsx index 7ccd3ae..f50a828 100644 --- a/web/src/app/(app)/providers.tsx +++ b/web/src/app/(app)/providers.tsx @@ -1,19 +1,19 @@ // app/providers.tsx -'use client' -import posthog from 'posthog-js' -import { PostHogProvider } from 'posthog-js/react' +"use client"; +import posthog from "posthog-js"; +import { PostHogProvider } from "posthog-js/react"; -if (typeof window !== 'undefined') { +if (typeof window !== "undefined") { posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY!, { api_host: process.env.NEXT_PUBLIC_POSTHOG_HOST, - capture_pageview: false // Disable automatic pageview capture, as we capture manually - }) + capture_pageview: false, // Disable automatic pageview capture, as we capture manually + }); } export function PHProvider({ children, }: { - children: React.ReactNode + children: React.ReactNode; }) { - return {children} + return {children}; } diff --git a/web/src/app/(app)/usage/loading.tsx b/web/src/app/(app)/usage/loading.tsx new file mode 100644 index 0000000..9ff4783 --- /dev/null +++ b/web/src/app/(app)/usage/loading.tsx @@ -0,0 +1,9 @@ +"use client"; + +import { LoadingPageWrapper } from "@/components/LoadingWrapper"; +import { usePathname } from "next/navigation"; + +export default function Loading() { + const pathName = usePathname(); + return ; +} diff --git a/web/src/app/(app)/usage/page.tsx b/web/src/app/(app)/usage/page.tsx new file mode 100644 index 0000000..9886f56 --- /dev/null +++ b/web/src/app/(app)/usage/page.tsx @@ -0,0 +1,57 @@ +import PricingList from "@/components/PricingPlan"; +import { Badge } from "@/components/ui/badge"; +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from "@/components/ui/card"; +import { Progress } from "@/components/ui/progress"; +import { getCurrentPlanWithAuth } from "@/server/getCurrentPlan"; +import { stripe } from "@/server/stripe"; + +const freeTierSeconds = 30000; + +export default async function Home() { + const sub = await getCurrentPlanWithAuth(); + + const data = sub?.subscription_item_api_id + ? await stripe.subscriptionItems.listUsageRecordSummaries( + sub?.subscription_item_api_id, + ) + : null; + + return ( +
+ + + Account Usage + View you account usage + {sub?.plan} + + {data && ( + +
+ Current free gpu usage: + { +
+ + {data.data[0].total_usage}s /{Math.floor(freeTierSeconds)}s + + + {Math.floor(data.data[0].total_usage / 60 / 60)}hr / + {Math.floor(freeTierSeconds / 60 / 60)}hr + +
+ } +
+ +
+ )} +
+
+ ); +} diff --git a/web/src/components/Navbar.tsx b/web/src/components/Navbar.tsx index d344683..07c4475 100644 --- a/web/src/components/Navbar.tsx +++ b/web/src/components/Navbar.tsx @@ -91,13 +91,22 @@ export function Navbar() {
{isDesktop && } {pricingPlanFlagEnable && ( - + <> + + + )}