From 9071cbdc25e97153086ac48bd389b04c43e56458 Mon Sep 17 00:00:00 2001 From: TheArcaneBrony Date: Fri, 19 Aug 2022 18:53:25 +0200 Subject: [PATCH] Updates scripts and tests from dev/plugins --- .githooks/pre-commit | 55 +++++++++ .gitignore | 5 +- .prettierrc | 6 +- assets/checkLocale.js | 90 +++++++-------- assets/developers.html | 76 ++++++------ assets/fosscord-login.css | 12 +- assets/fosscord.css | 68 +++++++++-- assets/index.html | 154 ++++++++++++------------- assets/schemas.json | Bin 40574 -> 24120 bytes assets/user.css | 2 +- build.json.default | 16 +++ docker-compose.cfg.yml | 7 +- docker-compose.yml | 41 ++++--- env-vars.md | 32 +++--- fosscord-server.code-workspace | 19 ++- package.json | 30 ++--- scripts/benchmark.js | 6 +- scripts/benchmark/connections.js | 6 +- scripts/benchmark/users.js | 4 +- scripts/build.js | 116 +++++++++++++------ scripts/build/clean.js | 18 +++ scripts/build/compile_tsc.js | 48 ++++++++ scripts/build/plugin_prepare.js | 31 +++++ scripts/build/plugin_resources.js | 13 +++ scripts/build/remap_imports.js | 15 +++ scripts/build_new.js | 31 +++++ scripts/code_quality.js | 75 ++++++++++++ scripts/depcheck.js | 44 +++---- scripts/depclean.js | 25 ++-- scripts/first_setup.js | 185 ++++++++++++++++++++++++++++++ scripts/gen_index.js | 47 ++++---- scripts/generate_schema.js | 11 +- scripts/migrate_db_engine.js | 6 +- scripts/rights.js | 18 +-- scripts/update_schemas.js | 2 +- scripts/utils.js | 48 +++++++- tests/cdn_endpoints.test.js | 96 +++++----------- tests/routes.test.ts | 8 +- tests/setupJest.js | 4 +- tsconfig.json | 164 +++++++++++++------------- 40 files changed, 1101 insertions(+), 533 deletions(-) create mode 100755 .githooks/pre-commit create mode 100644 build.json.default create mode 100644 scripts/build/clean.js create mode 100644 scripts/build/compile_tsc.js create mode 100644 scripts/build/plugin_prepare.js create mode 100644 scripts/build/plugin_resources.js create mode 100644 scripts/build/remap_imports.js create mode 100644 scripts/build_new.js create mode 100644 scripts/code_quality.js create mode 100644 scripts/first_setup.js diff --git a/.githooks/pre-commit b/.githooks/pre-commit new file mode 100755 index 000000000..0d2c8db78 --- /dev/null +++ b/.githooks/pre-commit @@ -0,0 +1,55 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed. +# Called by "git commit" with no arguments. The hook should +# exit with non-zero status after issuing an appropriate message if +# it wants to stop the commit. +# +# To enable this hook, rename this file to "pre-commit". + +if git rev-parse --verify HEAD >/dev/null 2>&1 +then + against=HEAD +else + # Initial commit: diff against an empty tree object + against=$(git hash-object -t tree /dev/null) +fi + +# If you want to allow non-ASCII filenames set this variable to true. +allownonascii=$(git config --type=bool hooks.allownonascii) + +# Redirect output to stderr. +exec 1>&2 + +# Cross platform projects tend to avoid non-ASCII filenames; prevent +# them from being added to the repository. We exploit the fact that the +# printable range starts at the space character and ends with tilde. +if [ "$allownonascii" != "true" ] && + # Note that the use of brackets around a tr range is ok here, (it's + # even required, for portability to Solaris 10's /usr/bin/tr), since + # the square bracket bytes happen to fall in the designated range. + test $(git diff --cached --name-only --diff-filter=A -z $against | + LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0 +then + cat <<\EOF +Error: Attempt to add a non-ASCII file name. + +This can cause problems if you want to work with people on other platforms. + +To be portable it is advisable to rename the file. + +If you know what you are doing you can disable this check using: + + git config hooks.allownonascii true +EOF + exit 1 +fi + +rm -rf dist + +#npx prettier -w . +npx --yes -p prettier@latest -p pretty-quick pretty-quick +git update-index --again + +# If there are whitespace errors, print the offending file names and fail. +#exec git diff-index --check --cached $against -- diff --git a/.gitignore b/.gitignore index e9f3f39c9..9629f85c1 100644 --- a/.gitignore +++ b/.gitignore @@ -19,5 +19,6 @@ api/assets/plugins/*.js bundle/depclean.* *.tmp tmp/ - -assets/cache/ \ No newline at end of file +assets/cache/ +*.generated +initial.json diff --git a/.prettierrc b/.prettierrc index 0defea238..cf69bed02 100644 --- a/.prettierrc +++ b/.prettierrc @@ -2,5 +2,7 @@ "tabWidth": 4, "useTabs": true, "printWidth": 140, - "trailingComma": "none" -} \ No newline at end of file + "trailingComma": "none", + "pluginSearchDirs": ["./node_modules"], + "plugins": ["prettier-plugin-organize-imports"] +} diff --git a/assets/checkLocale.js b/assets/checkLocale.js index 016d66c80..091add1fc 100644 --- a/assets/checkLocale.js +++ b/assets/checkLocale.js @@ -1,47 +1,47 @@ - const localStorage = window.localStorage; - // TODO: remote auth - // window.GLOBAL_ENV.REMOTE_AUTH_ENDPOINT = window.GLOBAL_ENV.GATEWAY_ENDPOINT.replace(/wss?:/, ""); - localStorage.setItem("gatewayURL", window.GLOBAL_ENV.GATEWAY_ENDPOINT); - localStorage.setItem( - "DeveloperOptionsStore", - `{"trace":false,"canary":false,"logGatewayEvents":true,"logOverlayEvents":true,"logAnalyticsEvents":true,"sourceMapsEnabled":false,"axeEnabled":false}` - ); +const localStorage = window.localStorage; +// TODO: remote auth +// window.GLOBAL_ENV.REMOTE_AUTH_ENDPOINT = window.GLOBAL_ENV.GATEWAY_ENDPOINT.replace(/wss?:/, ""); +localStorage.setItem("gatewayURL", window.GLOBAL_ENV.GATEWAY_ENDPOINT); +localStorage.setItem( + "DeveloperOptionsStore", + `{"trace":false,"canary":false,"logGatewayEvents":true,"logOverlayEvents":true,"logAnalyticsEvents":true,"sourceMapsEnabled":false,"axeEnabled":false}` +); - const supportedLocales = [ - "bg", - "cs", - "da", - "de", - "el", - "en-GB", - "es-ES", - "fi", - "fr", - "hi", - "hr", - "hu", - "it", - "ja", - "ko", - "lt", - "nl", - "no", - "pl", - "pt-BR", - "ro", - "ru", - "sv-SE", - "th", - "tr", - "uk", - "vi", - "zh-CN", - "zh-TW" - ]; +const supportedLocales = [ + "bg", + "cs", + "da", + "de", + "el", + "en-GB", + "es-ES", + "fi", + "fr", + "hi", + "hr", + "hu", + "it", + "ja", + "ko", + "lt", + "nl", + "no", + "pl", + "pt-BR", + "ro", + "ru", + "sv-SE", + "th", + "tr", + "uk", + "vi", + "zh-CN", + "zh-TW" +]; - const settings = JSON.parse(localStorage.getItem("UserSettingsStore")); - if (settings && !supportedLocales.includes(settings.locale)) { - // fix client locale wrong and client not loading at all - settings.locale = "en-US"; - localStorage.setItem("UserSettingsStore", JSON.stringify(settings)); - } \ No newline at end of file +const settings = JSON.parse(localStorage.getItem("UserSettingsStore")); +if (settings && !supportedLocales.includes(settings.locale)) { + // fix client locale wrong and client not loading at all + settings.locale = "en-US"; + localStorage.setItem("UserSettingsStore", JSON.stringify(settings)); +} diff --git a/assets/developers.html b/assets/developers.html index 87595e779..b33009ddd 100644 --- a/assets/developers.html +++ b/assets/developers.html @@ -1,44 +1,42 @@ + + + - - - + + + Discord Test Client Developer Portal + + - - - Discord Test Client Developer Portal - - + +
+ - - - - - - \ No newline at end of file + BRAINTREE_KEY: "production_5st77rrc_49pp2rp4phym7387", + STRIPE_KEY: "pk_live_CUQtlpQUF0vufWpnpUmQvcdi", + MARKETING_ENDPOINT: "//discord.com", + RELEASE_CHANNEL: "stable", + ALGOLIA_KEY: "aca0d7082e4e63af5ba5917d5e96bed0" + }; + GLOBAL_ENV.MEDIA_PROXY_ENDPOINT = location.protocol + "//" + GLOBAL_ENV.CDN_HOST; + const localStorage = window.localStorage; + // TODO: remote auth + // window.GLOBAL_ENV.REMOTE_AUTH_ENDPOINT = window.GLOBAL_ENV.GATEWAY_ENDPOINT.replace(/wss?:/, ""); + localStorage.setItem("gatewayURL", window.GLOBAL_ENV.GATEWAY_ENDPOINT); + localStorage.setItem( + "DeveloperOptionsStore", + `{"trace":false,"canary":false,"logGatewayEvents":true,"logOverlayEvents":true,"logAnalyticsEvents":true,"sourceMapsEnabled":false,"axeEnabled":false}` + ); + + + + + + diff --git a/assets/fosscord-login.css b/assets/fosscord-login.css index d507c5454..975bf908a 100644 --- a/assets/fosscord-login.css +++ b/assets/fosscord-login.css @@ -1,12 +1,12 @@ /* replace tos acceptance popup */ #app-mount > div:nth-child(7) > div > div > div.tooltipContent-bqVLWK { - visibility: hidden; + visibility: hidden; } -#app-mount > div:nth-child(7) > div > div > div.tooltipContent-bqVLWK::after{ - visibility: visible; - display: block; - content: "You need to agree to this instance's rules to continue"; - margin-top: -32px; +#app-mount > div:nth-child(7) > div > div > div.tooltipContent-bqVLWK::after { + visibility: visible; + display: block; + content: "You need to agree to this instance's rules to continue"; + margin-top: -32px; } /* replace login header */ #app-mount > div.app-1q1i1E > div > div > div > div > form > div > div > div.mainLoginContainer-1ddwnR > h3 { diff --git a/assets/fosscord.css b/assets/fosscord.css index 6078fdeb4..fa503d397 100644 --- a/assets/fosscord.css +++ b/assets/fosscord.css @@ -1,4 +1,3 @@ - /* loading spinner */ #app-mount > div.app-1q1i1E > div.container-16j22k.fixClipping-3qAKRb > div.content-1-zrf2 > video { filter: opacity(1); @@ -11,14 +10,62 @@ } /* home button icon */ -#app-mount > div.app-1q1i1E > div > div.layers-3iHuyZ.layers-3q14ss > div > div > nav > ul > div.scroller-1Bvpku.none-2Eo-qx.scrollerBase-289Jih > div.tutorialContainer-2sGCg9 > div > div.listItemWrapper-KhRmzM > div > svg > foreignObject > div > div -{ - background-image: url(https://raw.githubusercontent.com/fosscord/fosscord/master/assets-rebrand/svg/Fosscord-Icon-Rounded-Subtract.svg); - background-size: contain; - border-radius: 50%; +#app-mount + > div.app-1q1i1E + > div + > div.layers-3iHuyZ.layers-3q14ss + > div + > div + > nav + > ul + > div.scroller-1Bvpku.none-2Eo-qx.scrollerBase-289Jih + > div.tutorialContainer-2sGCg9 + > div + > div.listItemWrapper-KhRmzM + > div + > svg + > foreignObject + > div + > div { + background-image: url(https://raw.githubusercontent.com/fosscord/fosscord/master/assets-rebrand/svg/Fosscord-Icon-Rounded-Subtract.svg); + background-size: contain; + border-radius: 50%; } -#app-mount > div.app-1q1i1E > div > div.layers-3iHuyZ.layers-3q14ss > div > div > nav > ul > div.scroller-1Bvpku.none-2Eo-qx.scrollerBase-289Jih > div.tutorialContainer-2sGCg9 > div > div.listItemWrapper-KhRmzM > div > svg > foreignObject > div > div, #app-mount > div.app-1q1i1E > div > div.layers-3iHuyZ.layers-3q14ss > div > div > nav > ul > div.scroller-1Bvpku.none-2Eo-qx.scrollerBase-289Jih > div.tutorialContainer-2sGCg9 > div > div.listItemWrapper-KhRmzM > div > svg > foreignObject > div > div:hover { +#app-mount + > div.app-1q1i1E + > div + > div.layers-3iHuyZ.layers-3q14ss + > div + > div + > nav + > ul + > div.scroller-1Bvpku.none-2Eo-qx.scrollerBase-289Jih + > div.tutorialContainer-2sGCg9 + > div + > div.listItemWrapper-KhRmzM + > div + > svg + > foreignObject + > div + > div, +#app-mount + > div.app-1q1i1E + > div + > div.layers-3iHuyZ.layers-3q14ss + > div + > div + > nav + > ul + > div.scroller-1Bvpku.none-2Eo-qx.scrollerBase-289Jih + > div.tutorialContainer-2sGCg9 + > div + > div.listItemWrapper-KhRmzM + > div + > svg + > foreignObject + > div + > div:hover { background-color: white; } /* Login QR */ @@ -40,7 +87,6 @@ /* Thread permissions etc popups */ #app-mount > div.app-1q1i1E > div > div.layers-3iHuyZ.layers-3q14ss > div > div > div > div.content-98HsJk > div.sidebar-2K8pFh.hasNotice-1XRy4h > nav > div.container-3O_wAf, /* home button icon */ -#app-mount > div.app-1q1i1E > div > div.layers-3iHuyZ.layers-3q14ss > div > div > nav > ul > div.scroller-1Bvpku.none-2Eo-qx.scrollerBase-289Jih > div.tutorialContainer-2sGCg9 > div > div.listItemWrapper-KhRmzM > div > svg > foreignObject > div > div > svg -{ - display: none; -} \ No newline at end of file +#app-mount > div.app-1q1i1E > div > div.layers-3iHuyZ.layers-3q14ss > div > div > nav > ul > div.scroller-1Bvpku.none-2Eo-qx.scrollerBase-289Jih > div.tutorialContainer-2sGCg9 > div > div.listItemWrapper-KhRmzM > div > svg > foreignObject > div > div > svg { + display: none; +} diff --git a/assets/index.html b/assets/index.html index 64a2bdbff..1d4e45433 100644 --- a/assets/index.html +++ b/assets/index.html @@ -1,84 +1,82 @@ + + + + Discord Test Client + + + + + + - - - - Discord Test Client - - - - - - + +
+ - - - - - - - - - \ No newline at end of file + + + + + + + + + diff --git a/assets/schemas.json b/assets/schemas.json index 0fe3dfa122a0f1ba5315ee66660ce2b4ab18fa29..e3200800d7e5a9bf1c43dc8b4782ac03e50b2f9a 100644 GIT binary patch literal 24120 zcmeHPX>Z)d8U8H)ip9ns?f7b%R459#b{ZInW5agh52--Ra%Z&@aY=@UWHs=A?=vUg zA&1A38wCvt*jkA@$9rG%4u89MwtgO0;#yR<@8dl`u=V-sw|i%2>*_Y=_AgCqX5^inQXFywDrtE49~}ZMUKlS;~^P6oDN}O0MuK_^-7n_!bNP ztT1}8vH)MG0ryKwoAth`^7BWJekrr`p?>;hR$M;X7Hn5NeEjtz{p<^XAU9wClcg^T z&MH2Ox?7&`ibn@tmh6&8TXyRx-%zWp3Xxt?Vq-&q*Ch`fIh{I-kbj+RdBLizn1#QP zENStWBB5ogE_o468+uubWIJ&z|HR`OkWUZP(Ivy{+SpMd2F+i7KzgXZb%v;0o} zm}8h7980CVD!+uqxaP%|A8vD)&Q~eCQI1JtO6(L*>w|P8h78ir zW$F33NUvEUw(tbTvB7tmuW}Y&!Ms~ApwX?lCD#sEx;lQ%)9UNtiU?;4#zv}8oRJC@R0K_O!@8KC{Z4pwY`2ll|lSdj25 z-4cIV#7@V0ovRBL`RVZeIFvjQna7?dU; zY0^eX-jF8`rL)L38&BTMBHC)KIVNYNN-CX=Zidq=)QwNF_$os7Y-rl}fo2|c1a4l= z3OIb4gESL7xRe-apD@OSv$dCA0B334l%HD9XVA-oVbOwwHyw3j8pDFeA{QV`Lr2Hs zMhL)oS3QvAA%f5)ouj}Q^?c$HNR}$zw}o-EaW5Xt82{CBdRax#%UuutFf z^s?GR)Sf(kY{KkT@J;Mofh1_G&ZX^zhy&vq`8A?X#W&Vo@K_1HU+^8EUw`pv%Xcb} zgyuXlhS3utWsp7-Y;>&y)y_OYmI$TWPEykHw#1ysz)Ky)kY?9V&dGCTnnoq|TK5Ps ztQlE{h|&odN%t>x#)x}1Pw#nV&2dgLeCqLxpQ~ZC1 z|9`>%uO6)M=hLt7iAT@me>{GMKk?aGq69O` zMQn-G=dv2OJ;`pc49hmzW+N)pWg7`=rmnsCrP)c9?GkYiRS3GCNpg=!O_IS+B-c1% zb~ng!jOv5339+Kg#;uJK6D+AC!sAw;Kn8juC>auxLiwD=jvk|lXO+(#N%5=IQ7d=y z(Vz`^>q1BumdpB&F3+?VM^!7kA@n92;()^)8^~!MP+OkfPMxOgm^Xj)z(wunhfx|* zgc53Ne1e$xscgS8%W?<3l@3lMAG)Ejqojpr-sr{zebkn(Xw5_E`vheGv4l7?NQ&}M)Q>3tF@;57^PX|mT9!#p+j}w ztk8-TeX}t%k$=h)5sL~@DUR4tkJyQ%3NS1Lc3y8VH>#BsO%FOXsnA~#RpP+2x`{f5 z0F~p93x#t;?7YC~e}obZOPYwtZ9_bzp(ExTM16=530y)v%4oxih^K5LPf^+e>9S*D z2V0I}U@I@av*QM3{Lhd_oWx>%62OsS1*hzKyY#8V2GfU9oTqvNkS177&fLG ze`@%(lT#b1=+NlrF{&6MV2J8R_~H4|`wHPNjQYGXQm zlC<}nvjUnIOBCRA1&|WerX}l`rK~`UqRdyX5d*9*j6LfyjZQn_M4n+p z8`YI&k{TO65bDxMj!3?ltxm0@GOG)%2JO|4X0(YCTj3Ca$5%vceKp2|MxMk!5~JYZ z4Ov>_0TaYa?sa>H>m#i;RUANDdvS?JRfHU{at*S_ly_9+Ljg8q3Mozv zTXe&vp(3v;n7BcMIuZC&^#hc8(c=#&fa`)mc1tRbdrf(uKVSbh1E;)stCe6xJiI z#8o>LiNu9cVEj;=Ur_FPm7?9BFQ{{&cy-Au9kCFVbAr`1;%0_PX8eLppd92{C9N|Y zSQ^JYGHkLk*0@~C39T&hXh=dGFm{2#@+2-Rq?_+RL8Z+sU8myLIsiprC?Q{W>0a8Y zZ>yjFt=MrzziO=sum5Q73Zd6s&VrmN#hinKHIc^+k#9*Z}q6!;p}$=!ypz z+oiq&m_%1fp$EkAQtV`vY|Eqas;2pMaL#mQd4@q#QHGtCO4{bm=jdxL&mvzSH_-X;#DW-SDj*8Jt7ORDqb5&g&dLCb;*$rxwGkJSpY0UyP>VS3~ z5Y{6Tg$C3lYjd)H=a%X<;(mCCCC*M?glqXM4-w_N*QPW+EDd^Snt2ILpvGssipfDo z?TB8s3bn%pnAB7Er&6mIlty72@Rl@6YQ;zfa5Yns!u+kycTrDMnfPH8~ozAg(Y3Ko0KAB4pNmn0<_ z4Ik~L>kl>L}!()* z_zHE8I@zvpYJ#MF#nP3ub;XXwe6`Dp6>HY|cd947$$9$m`SUk_fB5hp&DRgh>Ner4 z1Fsm)kJ$?L(UzhN9jwGq^$nYovVxygw>${~!_&3y2L(jwz5JobGbs8J(gms3>m7T6 zSg@QGQn}!+lYbCtHyp-+BF71Ou*^cG^$4uJh||Gxv6LdJjrKcP@qDkDI*T^m8Ppn; zFV{FqN?-2Tv+-Wi;4x6Jl`teyh6@#K!|@sspANROP8UUwDT)ZP>>{^a%9yuBoz4sW z!`ITi2x%sQYURa<)u>j?60!}4!3*T{UG>A||4=ss9XOK&dSx)#0JD@D@6`S7z6&(O zcL&b?RN3=L&9mxgjWs2S^=<7;pQ`f{<145tem%Y@oDEJ5nxizQw4O240N||`f@C+~ z`GLuqIAfMy7y$YaK%EmWoygHn8Q8CjFKz;({5Hjl%eJd1+eI5usGj&%4$@uvxZ;Dx z{>XX=3cd&Q9m%(8M2bF9mg9O-AS&@FJyZHE8zKKPsMW{)67B^)`5i}pJrF4OB7d8e z)hyGn74ql=f-2u_F@={7{6S|vlT1D|zZY)Xmgvb~J^&}nrubEs{#$vB#P1MoE!1tKQFE*P)b-w~3aYx|z2 zUlf)5n>cbP8Q0AB;y@(0(0Rw-3rFesguKIU=wRd>(maRO7c{5;@)N^5gl>NoFC0I#gY} z3#$K=p#%E8?6Dh)c}Ykcs_h(i)Yv&$3B|z1#g%nFz5h}Mwz97e7b44?GkyC9ZCr=` z*Yz3YZt6C&Zt_sx8lo@7EP1kv4t1#V5=fTR=q+dRGJmV=(l`2AY&kJOHiGqrPnQNS zz$d&}>L5Py%|6Sn795ECDKfRR-wY{&v9sZ;k6vaulSn6t^FInSNmL6w=rLDM2wOW+ zMqSiQf{^7AU|7JG3eXGP7QcW*{Q@*4n6T9(5C!?V?Z`j%YZ{z6qgRc!2>UN+a04mB z^uS;Zr6+pSGd8W4GPuP96&e|;={GBMO;lj`&>iogZCq8MBcXv!nyOgn!syW?`Xf7OL&1%+6~F!p6tj6;j08j#QSckYe31eo!2bbji_1k z0BOHqp>KlT$|5j&QY}&P9LM-;6=YG?mYupUR0zSPp`oN780Ec0!Hx5Lq89zY>l55? z!cMcfy$U`2;sm!qKva8rpaLW9UK3uH5Z(|JR$z~^FW56bB8*NgeM|UzzB1w7=X?JJ D=blQ& literal 40574 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 x?.name) - .includes(name); + return ![Models.BaseClassWithoutId, PrimaryColumn, Models.BaseClass, Models.PrimaryGeneratedColumn].map((x) => x?.name).includes(name); } async function main() { @@ -14,7 +12,7 @@ async function main() { type: "sqlite", database: ":memory:", entities: Object.values(Models).filter((x) => x.constructor.name == "Function" && shouldIncludeEntity(x.name)), - synchronize: true, + synchronize: true }); await db.initialize(); console.log("Initialized database"); diff --git a/scripts/benchmark/connections.js b/scripts/benchmark/connections.js index 661548c38..f74d0c6dc 100644 --- a/scripts/benchmark/connections.js +++ b/scripts/benchmark/connections.js @@ -8,7 +8,7 @@ let cores = 1; try { cores = Number(process.env.THREADS) || os.cpus().length; } catch { - console.log("[Bundle] Failed to get thread count! Using 1...") + console.log("[Bundle] Failed to get thread count! Using 1..."); } if (!token) { @@ -46,8 +46,8 @@ function connect() { op: 2, d: { token, - properties: {}, - }, + properties: {} + } }) ); diff --git a/scripts/benchmark/users.js b/scripts/benchmark/users.js index bce67bf43..415d6d8b7 100644 --- a/scripts/benchmark/users.js +++ b/scripts/benchmark/users.js @@ -14,9 +14,9 @@ async function main() { consent: true, date_of_birth: "2000-01-01", gift_code_sku_id: null, - captcha_key: null, + captcha_key: null }), - headers: { "content-type": "application/json" }, + headers: { "content-type": "application/json" } }); console.log(i); } diff --git a/scripts/build.js b/scripts/build.js index 2c0d73285..f618100ca 100644 --- a/scripts/build.js +++ b/scripts/build.js @@ -2,20 +2,22 @@ const { execSync } = require("child_process"); const path = require("path"); const fs = require("fs"); const { argv, stdout, exit } = require("process"); -const { execIn, parts } = require('./utils'); +const { execIn, parts, getDirs, walk, sanitizeVarName } = require("./utils"); -if(argv.includes("help")) { +if (argv.includes("help")) { console.log(`Fosscord build script help: Arguments: clean Cleans up previous builds verbose Enable verbose logging logerrors Log build errors to console pretty-errors Pretty-print build errors - silent No output to console or files.`); + silent No output to console or files. + propagate-err Exit script with error code if build fails.`); exit(0); } -let steps = 1, i = 0; +let steps = 5, + i = 0; if (argv.includes("clean")) steps++; const verbose = argv.includes("verbose") || argv.includes("v"); @@ -23,7 +25,7 @@ const logerr = argv.includes("logerrors"); const pretty = argv.includes("pretty-errors"); const silent = argv.includes("silent"); -if(silent) console.error = console.log = function(){} +if (silent) console.error = console.log = function () {}; if (argv.includes("clean")) { console.log(`[${++i}/${steps}] Cleaning...`); @@ -36,37 +38,79 @@ if (argv.includes("clean")) { console.log(`[${++i}/${steps}] Compiling src files ...`); -let buildFlags = '' -if(pretty) buildFlags += '--pretty ' +let buildFlags = ""; +if (pretty) buildFlags += "--pretty "; -try { - execSync( - 'node "' + - path.join(__dirname, "..", "node_modules", "typescript", "lib", "tsc.js") + - '" -p "' + - path.join(__dirname, "..") + - '" ' + buildFlags, - { - cwd: path.join(__dirname, ".."), - shell: true, - env: process.env, - encoding: "utf8" - } - ) -} catch (error) { - if(verbose || logerr) { - error.stdout.split(/\r?\n/).forEach((line) => { - let _line = line.replace('dist/','',1); - if(!pretty && _line.includes('.ts(')) { - //reformat file path for easy jumping - _line = _line.replace('(',':',1).replace(',',':',1).replace(')','',1) +console.log(`[${++i}/${steps}] Building plugin index...`); +let pluginDir = path.join(__dirname, "..", "src", "plugins"); +let output = 'import { Plugin } from "util/plugin";\n'; + +const dirs = fs.readdirSync(pluginDir).filter((x) => { + try { + fs.readdirSync(path.join(pluginDir, x)); + return true; + } catch (e) { + return false; + } +}); +dirs.forEach((x) => { + let pluginManifest = require(path.join(pluginDir, x, "plugin.json")); + output += `import * as ${sanitizeVarName(x)} from "./${x}/${pluginManifest.mainClass}";\n`; +}); +output += `\nexport const PluginIndex: any = {\n`; +dirs.forEach((x) => { + output += ` "${x}": new ${sanitizeVarName(x)}.default(),\n`; //ctor test: '${path.resolve(path.join(pluginDir, x))}', require('./${x}/plugin.json') +}); +output += `};`; + +fs.writeFileSync(path.join(__dirname, "..", "src", "plugins", "PluginIndex.ts"), output); + +if (!argv.includes("copyonly")) { + console.log(`[${++i}/${steps}] Compiling source code...`); + + let buildFlags = ""; + if (pretty) buildFlags += "--pretty "; + + try { + execSync( + 'node "' + + path.join(__dirname, "..", "node_modules", "typescript", "lib", "tsc.js") + + '" -p "' + + path.join(__dirname, "..") + + '" ' + + buildFlags, + { + cwd: path.join(__dirname, ".."), + shell: true, + env: process.env, + encoding: "utf8" } - console.error(_line); - }) + ); + } catch (error) { + if (verbose || logerr) { + error.stdout.split(/\r?\n/).forEach((line) => { + let _line = line.replace("dist/", "", 1); + if (!pretty && _line.includes(".ts(")) { + //reformat file path for easy jumping + _line = _line.replace("(", ":", 1).replace(",", ":", 1).replace(")", "", 1); + } + console.error(_line); + }); + } + console.error(`Build failed! Please check build.log for info!`); + if (!silent) { + if (pretty) fs.writeFileSync("build.log.ansi", error.stdout); + fs.writeFileSync( + "build.log", + error.stdout.replaceAll(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, "") + ); + } + throw error; } - console.error(`Build failed! Please check build.log for info!`); - if(!silent){ - if(pretty) fs.writeFileSync("build.log.ansi", error.stdout); - fs.writeFileSync("build.log", error.stdout.replaceAll(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, '')); - } -} \ No newline at end of file +} + +console.log(`[${++i}/${steps}] Copying plugin data...`); +let pluginFiles = walk(pluginDir).filter((x) => !x.endsWith(".ts")); +pluginFiles.forEach((x) => { + fs.copyFileSync(x, x.replace("src", "dist")); +}); diff --git a/scripts/build/clean.js b/scripts/build/clean.js new file mode 100644 index 000000000..92ec6d775 --- /dev/null +++ b/scripts/build/clean.js @@ -0,0 +1,18 @@ +const { execSync } = require("child_process"); +const path = require("path"); +const fs = require("fs"); +const { argv, stdout, exit } = require("process"); +const { execIn, parts, getDirs, walk, sanitizeVarName } = require("../utils"); + +module.exports = function (config) { + if (fs.existsSync(config.buildLog)) fs.rmSync(config.buildLog); + if (fs.existsSync(config.buildLogAnsi)) fs.rmSync(config.buildLogAnsi); + + if (config.clean) { + console.log(`==> Cleaning...`); + if (fs.existsSync(config.distDir)) { + fs.rmSync(config.distDir, { recursive: true }); + if (config.verbose) console.log(`Deleted ${path.resolve(config.distDir)}!`); + } + } +}; diff --git a/scripts/build/compile_tsc.js b/scripts/build/compile_tsc.js new file mode 100644 index 000000000..179707a36 --- /dev/null +++ b/scripts/build/compile_tsc.js @@ -0,0 +1,48 @@ +const { execSync } = require("child_process"); +const path = require("path"); +const fs = require("fs"); +const { argv, stdout, exit } = require("process"); +const { execIn, parts, getDirs, walk, sanitizeVarName } = require("../utils"); + +module.exports = function (config) { + console.log("==> Compiling source with tsc..."); + let buildFlags = ""; + if (config.pretty) buildFlags += "--pretty "; + + try { + execSync( + 'node "' + + path.join(config.rootDir, "node_modules", "typescript", "lib", "tsc.js") + + '" -p "' + + path.join(config.rootDir) + + '" ' + + buildFlags, + { + cwd: path.join(config.rootDir), + shell: true, + env: process.env, + encoding: "utf8" + } + ); + } catch (error) { + if (config.verbose || config.logerr) { + error.stdout.split(/\r?\n/).forEach((line) => { + let _line = line.replace("dist/", "", 1); + if (!config.pretty && _line.includes(".ts(")) { + //reformat file path for easy jumping + _line = _line.replace("(", ":", 1).replace(",", ":", 1).replace(")", "", 1); + } + console.error(_line); + }); + } + console.error(`Build failed! Please check build.log for info!`); + if (!config.silent) { + if (config.pretty) fs.writeFileSync(path.join(config.rootDir, "build.log.ansi"), error.stdout); + fs.writeFileSync( + path.join(config.rootDir, "build.log"), + error.stdout.replaceAll(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, "") + ); + } + throw error; + } +}; diff --git a/scripts/build/plugin_prepare.js b/scripts/build/plugin_prepare.js new file mode 100644 index 000000000..247ad22d0 --- /dev/null +++ b/scripts/build/plugin_prepare.js @@ -0,0 +1,31 @@ +const { execSync } = require("child_process"); +const path = require("path"); +const fs = require("fs"); +const { argv, stdout, exit } = require("process"); +const { execIn, parts, getDirs, walk, sanitizeVarName } = require("../utils"); + +module.exports = function (config) { + console.log(`==> Building plugin index...`); + let output = 'import { Plugin } from "util/plugin";\n'; + + const dirs = fs.readdirSync(config.pluginDir).filter((x) => { + try { + fs.readdirSync(path.join(config.pluginDir, x)); + return true; + } catch (e) { + return false; + } + }); + dirs.forEach((x) => { + let pluginManifest = require(path.join(config.pluginDir, x, "plugin.json")); + console.log(` ==> Registering plugin: ${pluginManifest.name} (${pluginManifest.id}) by ${pluginManifest.authors}`); + output += `import * as ${sanitizeVarName(x)} from "./${x}/${pluginManifest.mainClass}";\n`; + }); + output += `\nexport const PluginIndex: any = {\n`; + dirs.forEach((x) => { + output += ` "${x}": new ${sanitizeVarName(x)}.default(),\n`; //ctor test: '${path.resolve(path.join(pluginDir, x))}', require('./${x}/plugin.json') + }); + output += `};`; + + fs.writeFileSync(path.join(config.pluginDir, "PluginIndex.ts"), output); +}; diff --git a/scripts/build/plugin_resources.js b/scripts/build/plugin_resources.js new file mode 100644 index 000000000..5b4b97f22 --- /dev/null +++ b/scripts/build/plugin_resources.js @@ -0,0 +1,13 @@ +const { execSync } = require("child_process"); +const path = require("path"); +const fs = require("fs"); +const { argv, stdout, exit } = require("process"); +const { execIn, parts, getDirs, walk, sanitizeVarName } = require("../utils"); + +module.exports = function (config) { + console.log(`==> Copying all plugin resources...`); + let pluginFiles = walk(config.pluginDir).filter((x) => !x.endsWith(".ts")); + pluginFiles.forEach((x) => { + fs.copyFileSync(x, x.replace("src", "dist")); + }); +}; diff --git a/scripts/build/remap_imports.js b/scripts/build/remap_imports.js new file mode 100644 index 000000000..cdcd571a6 --- /dev/null +++ b/scripts/build/remap_imports.js @@ -0,0 +1,15 @@ +const { execSync } = require("child_process"); +const path = require("path"); +const fs = require("fs"); +const { argv, stdout, exit } = require("process"); +const { execIn, parts, getDirs, walk, sanitizeVarName } = require("../utils"); + +module.exports = function (config) { + console.log(`==> Remapping module imports...`); + let files = walk(config.distDir).filter((x) => x.endsWith(".js")); + files.forEach((x) => { + let fc = fs.readFileSync(x).toString(); + fc = fc.replaceAll("@fosscord/", "#"); + fs.writeFileSync(x, fc); + }); +}; diff --git a/scripts/build_new.js b/scripts/build_new.js new file mode 100644 index 000000000..6a56e7f7e --- /dev/null +++ b/scripts/build_new.js @@ -0,0 +1,31 @@ +const { execSync } = require("child_process"); +const path = require("path"); +const fs = require("fs"); +const { argv, stdout, exit } = require("process"); +const { execIn, parts, getDirs, walk, sanitizeVarName } = require("./utils"); + +//file paths +const rootDir = path.join(__dirname, ".."); +const srcDir = path.join(rootDir, "src"); +const distDir = path.join(rootDir, "dist"); +const scriptsDir = path.join(rootDir, "scripts"); +const configPath = path.join(rootDir, "build.json"); +const buildLog = path.join(rootDir, "build.log"); +const buildLogAnsi = path.join(rootDir, "build.log.ansi"); +const pluginDir = path.join(srcDir, "plugins"); + +//more, dont export +const buildStepDir = path.join(scriptsDir, "build"); + +if (!fs.existsSync(configPath)) { + if (!fs.existsSync(path.join(configPath + ".default"))) { + console.log("build.json.default not found! Exiting!"); + exit(1); + } + fs.copyFileSync(configPath + ".default", configPath); +} +let config = { rootDir, srcDir, distDir, configPath, buildLog, buildLogAnsi, pluginDir, ...require(configPath) }; + +config.steps.pre.forEach((step) => require(path.join(buildStepDir, step))(config)); +require(path.join(buildStepDir, "compile_" + config.compiler))(config); +config.steps.post.forEach((step) => require(path.join(buildStepDir, step))(config)); diff --git a/scripts/code_quality.js b/scripts/code_quality.js new file mode 100644 index 000000000..aca01d245 --- /dev/null +++ b/scripts/code_quality.js @@ -0,0 +1,75 @@ +const path = require("path"); +const fs = require("fs").promises; +const { execIn, getLines, walk, projectRoot } = require("./utils"); + +let printTodos = process.argv.includes("TODOS"); + +let root = path.resolve(path.join(__dirname, "..", "src")); +let files = walk(root); +let _files = []; +let errors = 0, + warnings = 0, + todos = 0; + +Promise.all(files.map(getFile)).then((f) => { + Promise.all(Object.keys(_files).map(checkFile)); + console.log(`\n${errors} errors, ${warnings} warnings, ${todos} TODOs.`); + + let loc = 0; + Object.values(_files).forEach((x) => { + loc += x.length; + }); + console.log("\nStats:\n"); + console.log(`Lines of code: ${loc} lines in ${Object.values(_files).length} files.`); + + debugger; +}); + +async function getFile(name) { + let contents = (await fs.readFile(name)).toString().split("\n"); + _files[name] = contents; +} + +async function checkFile(x) { + _files[x].forEach((line) => scanLine(x, line)); +} + +function log(file, line, msg) { + let lineNum = _files[file].indexOf(line) + 1; + console.log(msg, "File:", file.replace(root + "/", "") + ":" + lineNum); +} + +function scanLine(x, line) { + if (/import/.test(line)) { + if (/import {?.*}? from '.*'/.test(line)) { + log(x, line, `[WARN] Inconsistent import syntax, please use double quotes!`); + warnings++; + } + } else { + if (line.trim().endsWith("TODO:")) { + log(x, line, `[ERRO] Empty TODO!`); + errors++; + } else if (/\/\/\s{0,3}TODO:/.test(line)) { + if (printTodos) log(x, line, `[TODO] Found a TODO: ${line.split("TODO:")[1].trim()}.`); + todos++; + } + if (/(:|=)/.test(line)) { + if (/(:|=) {2,}/.test(line)) { + log(x, line, `[WARN] Multiple spaces in assignment!`); + warnings++; + } + if (/(:|=)\t'/.test(line)) { + log(x, line, `[WARN] Tab in assignment!`); + warnings++; + } + if (/(:|=)\w'/.test(line)) { + log(x, line, `[WARN] Missing space in assignment!`); + warnings++; + } + if (/(:|=) undefined/.test(line) && !/(:|=){2,} undefined/.test(line)) { + log(x, line, `[WARN] Use of undefined!`); + warnings++; + } + } + } +} diff --git a/scripts/depcheck.js b/scripts/depcheck.js index 08df156cf..44ac2bb66 100644 --- a/scripts/depcheck.js +++ b/scripts/depcheck.js @@ -9,22 +9,22 @@ const { execIn, getLines } = require("./utils"); let npmi_extra_flags = ""; const resolveminor = argv.includes("resolveminor"); -if(argv.includes("nobuild")) npmi_extra_flags += "--ignore-scripts "; +if (argv.includes("nobuild")) npmi_extra_flags += "--ignore-scripts "; parts.forEach((part) => { let partDir = path.join(__dirname, "..", "..", part); let distDir = path.join(partDir, "dist"); console.log(`Checking updates for ${part} (${partDir})`); - if(part == "bundle") { - execIn(`npm run syncdeps`, partDir) + if (part == "bundle") { + execIn(`npm run syncdeps`, partDir); } - if(resolveminor) { - fs.rmSync(path.join(partDir, "node_modules"), { + if (resolveminor) { + fs.rmSync(path.join(partDir, "node_modules"), { recursive: true, - force: true, + force: true }); - execIn(`npm i --save --no-fund --no-audit --no-package-lock ${npmi_extra_flags}`, partDir) - } + execIn(`npm i --save --no-fund --no-audit --no-package-lock ${npmi_extra_flags}`, partDir); + } let x = [ [ "pkg", @@ -33,24 +33,18 @@ parts.forEach((part) => { wanted: "2.0", latest: "2.0", dependent: "cdn", - location: "/usr/src/fosscord/bundle/node_packages/pkg", - }, - ], + location: "/usr/src/fosscord/bundle/node_packages/pkg" + } + ] ]; - x = Object.entries( - JSON.parse(execIn("npm outdated --json", partDir)) - ); + x = Object.entries(JSON.parse(execIn("npm outdated --json", partDir))); x.forEach((a) => { - let pkgname = a[0]; - let pkginfo = a[1]; - if(!pkginfo.current) - console.log(`MISSING ${pkgname}: ${pkginfo.current} -> ${pkginfo.wanted} (latest: ${pkginfo.latest})`); - else if(pkginfo.latest != pkginfo.wanted){ - if(pkginfo.current != pkginfo.wanted) - console.log(`MINOR ${pkgname}: ${pkginfo.current} -> ${pkginfo.wanted}`); - console.log(`MAJOR ${pkgname}: ${pkginfo.current} -> ${pkginfo.latest}`); - } - else - console.log(`MINOR ${pkgname}: ${pkginfo.current} -> ${pkginfo.wanted}`); + let pkgname = a[0]; + let pkginfo = a[1]; + if (!pkginfo.current) console.log(`MISSING ${pkgname}: ${pkginfo.current} -> ${pkginfo.wanted} (latest: ${pkginfo.latest})`); + else if (pkginfo.latest != pkginfo.wanted) { + if (pkginfo.current != pkginfo.wanted) console.log(`MINOR ${pkgname}: ${pkginfo.current} -> ${pkginfo.wanted}`); + console.log(`MAJOR ${pkgname}: ${pkginfo.current} -> ${pkginfo.latest}`); + } else console.log(`MINOR ${pkgname}: ${pkginfo.current} -> ${pkginfo.wanted}`); }); }); diff --git a/scripts/depclean.js b/scripts/depclean.js index 333f5aa00..5a4023310 100644 --- a/scripts/depclean.js +++ b/scripts/depclean.js @@ -3,8 +3,7 @@ const fs = require("fs"); const { env } = require("process"); const { execSync } = require("child_process"); const { argv, stdout, exit } = require("process"); - -const { execIn, getLines } = require('./utils'); +const { execIn, getLines } = require("./utils"); const bundleRequired = ["@ovos-media/ts-transform-paths"]; const removeModules = argv.includes("cleanup"); @@ -15,13 +14,11 @@ execIn("npm i", path.join(__dirname, "..")); let partDir = path.join(__dirname, ".."); let distDir = path.join(partDir, "dist"); let start = 0; -start = getLines( - execIn("npm ls --parseable --package-lock-only -a", partDir) -); +start = getLines(execIn("npm ls --parseable --package-lock-only -a", partDir)); if (fs.existsSync(distDir)) fs.rmSync(distDir, { recursive: true, - force: true, + force: true }); let x = { dependencies: [], @@ -29,17 +26,13 @@ let x = { invalidDirs: [], invalidFiles: [], missing: [], - using: [], + using: [] }; let dcproc = execIn("npx depcheck --json", partDir); -if(dcproc.stdout) x = JSON.parse(dcproc.stdout); +if (dcproc.stdout) x = JSON.parse(dcproc.stdout); else x = JSON.parse(dcproc); -fs.writeFileSync( - path.join(__dirname, "..", `depclean.out.json`), - JSON.stringify(x, null, "\t"), - { encoding: "utf8" } -); +fs.writeFileSync(path.join(__dirname, "..", `depclean.out.json`), JSON.stringify(x, null, "\t"), { encoding: "utf8" }); let depsToRemove = x.dependencies.join(" "); if (depsToRemove) execIn(`npm r --save ${depsToRemove}`, partDir); @@ -50,11 +43,9 @@ if (depsToRemove) execIn(`npm r --save --dev ${depsToRemove}`, partDir); if (removeModules && fs.existsSync(path.join(partDir, "node_modules"))) fs.rmSync(path.join(partDir, "node_modules"), { recursive: true, - force: true, + force: true }); -let end = getLines( - execIn("npm ls --parseable --package-lock-only -a", partDir) -); +let end = getLines(execIn("npm ls --parseable --package-lock-only -a", partDir)); console.log(`${part}: ${start} -> ${end} (diff: ${start - end})`); console.log("Installing required packages for bundle..."); diff --git a/scripts/first_setup.js b/scripts/first_setup.js new file mode 100644 index 000000000..24088eeee --- /dev/null +++ b/scripts/first_setup.js @@ -0,0 +1,185 @@ +const path = require("path"); +const fs = require("fs"); +const { stdout, exit } = require("process"); +const readline = require("readline"); + +const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); +const data = { env: [], config: { register: {} } }; +let rights = []; + +console.log("Welcome to Fosscord!"); +console.log("Please remember this is pre-release software!"); +console.log("We will guide you through some important setup steps."); +console.log(); + +async function main() { + printTitle("Step 1: Database setup"); + console.log("1. PostgreSQL (recommended)"); + console.log("2. MariaDB/MySQL"); + console.log("3. SQLite (not recommended, but good for a simple test)"); + + while (!data.db) { + let answer = await ask("Please select a database type: "); + if (answer == "1") { + data.db = "postgres"; + } else if (answer == "2") { + data.db = "mariadb"; + } else if (answer == "3") { + data.db = "sqlite"; + } else { + console.log("Invalid choice!"); + } + } + + printTitle("Step 2: Database credentials"); + if (data.db != "sqlite") { + console.log("Please enter your database credentials."); + console.log("You can leave the password field empty if you don't want to set a password."); + console.log(); + while (!data.db_host) { + data.db_host = await ask("Host: "); + } + while (!data.db_port) { + data.db_port = await ask("Port: "); + } + while (!data.db_user) { + data.db_user = await ask("Username: "); + } + while (!data.db_pass) { + data.db_pass = await ask("Password: "); + } + while (!data.db_name) { + data.db_name = await ask("Database name: "); + } + } else { + console.log("SQLite does not use credentials..."); + } + + printTitle("Step 3: Domain setup"); + console.log("Please enter your domain."); + console.log("You can leave the port field empty if you don't want to set a port."); + console.log(); + + data.domain = await ask("Domain (default=localhost): "); + if (!data.domain) data.domain = "localhost"; + else data.ssl = /y?/i.test(await ask("SSL/HTTPS (Y/n): ")).toLowerCase(); + + data.port = await ask("Port (default=3001): "); + if (!data.port) data.port = "3001"; + + if (data.db != "sqlite") + data.env.push(`DATABASE=${data.db}://${data.db_user}:${data.db_pass}@${data.db_host}:${data.db_port}/${data.db_name}`); + data.env.push(`PORT=${data.port}`); + + printTitle("Step 4: Default rights"); + console.log("Please enter the default rights for new users."); + console.log("Valid rights are: none, discord, full, custom."); + console.log(); + let lines = fs.readFileSync(path.join(__dirname, "..", "src", "util", "util", "Rights.ts")).toString(); + let lines2 = lines.split("\n"); + let lines3 = lines2.filter((y) => y.includes(": BitFlag(")); + let lines4 = lines3.map((x) => x.split("//")[0].trim()); + + let maxRights = 0n; + lines4.forEach((x) => { + maxRights += eval(`rights.${x.replace(":", " = ").replace(",", ";")}`); + }); + discordRights = maxRights; + discordRights -= rights.SEND_BACKDATED_EVENTS; + discordRights -= rights.MANAGE_GUILD_DIRECTORY; + discordRights -= rights.CREDITABLE; + discordRights -= rights.BYPASS_RATE_LIMITS; + discordRights -= rights.ADD_MEMBERS; + discordRights -= rights.MANAGE_RATE_LIMITS; + discordRights -= rights.OPERATOR; + + data.default_rights = await ask("Rights (default=none): "); + if (!data.default_rights || data.defaultRights == "none") data.config.register.defaultRights = "0"; + else if (data.default_rights == "discord") data.config.register.defaultRights = discordRights.toString(); + else if (data.default_rights == "full") data.config.register.defaultRights = maxRights.toString(); + else if (data.default_rights == "custom") data.config.register.defaultRights = (await askRights()).toString(); + + if (data.domain != "localhost") + data.config = { + cdn: { + endpointPrivate: `http://localhost:${data.port}`, + endpointPublic: `${data.ssl ? "https" : "http"}://${data.domain}:${data.port}` + }, + gateway: { + endpointPrivate: `ws://localhost:${data.port}`, + endpointPublic: `${data.ssl ? "wss" : "ws"}://${data.domain}:${data.port}` + }, + ...data.config + }; + //save + fs.writeFileSync(".env", data.env.join("\n")); + fs.writeFileSync("initial.json", JSON.stringify(data.config, (space = 4))); + exit(0); +} +main(); + +async function askRights() { + let w = 0; + let brights = { ...eval(`rights`) }; + Object.keys(rights).forEach((x) => { + brights[x] = false; + let str = `[x] ${Object.keys(rights).length}: ${x}`; + if (str.length > w) w = str.length; + }); + + let resp = ""; + let selectedRights = 0n; + while (resp != "q") { + selectedRights = 0n; + Object.keys(brights).forEach((x) => { + if (brights[x]) selectedRights += rights[x]; + }); + console.clear(); + printTitle("Step 4: Default rights"); + printTitle(`Current rights: ${selectedRights} (0b${selectedRights.toString(2)}, 0x${selectedRights.toString(16)})`); + let xpos = 0; + Object.keys(rights).forEach((x) => { + let str = `[${brights[x] ? "X" : " "}] ${Object.keys(rights).indexOf(x)}: ${x}`.padEnd(w + 1, " "); + if (xpos + str.length > stdout.columns) { + console.log(); + xpos = 0; + } + stdout.write(str); + xpos += str.length; + }); + + console.log(); + resp = await ask("Enter an option, or q to exit: "); + if (/\d{1,}/.test(resp) && resp < Object.keys(rights).length && resp > -1) { + brights[Object.keys(brights)[parseInt(resp)]] ^= true; + } + } + return selectedRights; +} + +async function askRight(right) { + let answer = await ask(`${right}: `); + if (answer == "y") return true; + else if (answer == "n") return false; + else return askRight(right); +} + +function printTitle(input) { + let width = stdout.columns / 2 - 1; //40 + console.log(); + console.log("-".repeat(width - input.length / 2), input, "-".repeat(width - input.length / 2)); + console.log(); +} +async function ask(question) { + return new Promise((resolve, reject) => { + return rl.question(question, (answer) => { + resolve(answer); + }); + }).catch((err) => { + console.log(err); + }); +} + +function BitFlag(int) { + return 1n << BigInt(int); +} diff --git a/scripts/gen_index.js b/scripts/gen_index.js index 71c64a9f7..8a3c7eb82 100644 --- a/scripts/gen_index.js +++ b/scripts/gen_index.js @@ -1,34 +1,37 @@ const path = require("path"); const fs = require("fs"); -const { execIn, getLines, parts } = require('./utils'); +const { execIn, getLines } = require("./utils"); if (!process.argv[2] || !fs.existsSync(process.argv[2])) { - console.log("Please pass a directory that exists!"); - process.exit(1); + console.log("Please pass a directory that exists!"); + process.exit(1); } -console.log(`// ${process.argv[2]}/index.ts`) -const recurse = process.argv.includes("--recursive") +console.log(`// ${process.argv[2]}/index.ts`); +const recurse = process.argv.includes("--recursive"); -const files = fs.readdirSync(process.argv[2]).filter(x => x.endsWith('.ts') && x != 'index.ts'); +const files = fs.readdirSync(process.argv[2]).filter((x) => x.endsWith(".ts") && x != "index.ts"); -let output = ''; +let output = ""; -files.forEach(x => output += `export * from "./${x.replaceAll('.ts','')}";\n`) +files.forEach((x) => (output += `export * from "./${x.replaceAll(".ts", "")}";\n`)); -const dirs = fs.readdirSync(process.argv[2]).filter(x => { - try { - fs.readdirSync(path.join(process.argv[2], x)); - return true; - } catch (e) { - return false; - } +const dirs = fs.readdirSync(process.argv[2]).filter((x) => { + try { + fs.readdirSync(path.join(process.argv[2], x)); + return true; + } catch (e) { + return false; + } +}); +dirs.forEach((x) => { + output += `export * from "./${x}/index";\n`; }); -dirs.forEach(x => { - output += `export * from "./${x}/index";\n` -}) console.log(output); -fs.writeFileSync(path.join(process.argv[2], "index.ts"), output) +fs.writeFileSync(path.join(process.argv[2], "index.ts"), output); -dirs.forEach(x => { - if(recurse) console.log(execIn([process.argv[0], process.argv[1], `"${path.join(process.argv[2], x)}"`, "--recursive"].join(' '), process.cwd())) -}) \ No newline at end of file +dirs.forEach((x) => { + if (recurse) + console.log( + execIn([process.argv[0], process.argv[1], `"${path.join(process.argv[2], x)}"`, "--recursive"].join(" "), process.cwd()) + ); +}); diff --git a/scripts/generate_schema.js b/scripts/generate_schema.js index 6925df5d2..e4bdd0c4b 100644 --- a/scripts/generate_schema.js +++ b/scripts/generate_schema.js @@ -36,7 +36,7 @@ const Excluded = [ "UncheckedPropertiesSchema", "PropertiesSchema", "AsyncSchema", - "AnySchema", + "AnySchema" ]; function modify(obj) { @@ -48,13 +48,8 @@ function modify(obj) { } function main() { - const files = [ - ...walk(path.join(__dirname, "..", "src", "util", "schemas")), - ]; - const program = TJS.getProgramFromFiles( - files, - compilerOptions - ); + const files = [...walk(path.join(__dirname, "..", "src", "util", "schemas"))]; + const program = TJS.getProgramFromFiles(files, compilerOptions); const generator = TJS.buildGenerator(program, settings); if (!generator || !program) return; diff --git a/scripts/migrate_db_engine.js b/scripts/migrate_db_engine.js index 79e9d86f4..b5b8008b0 100644 --- a/scripts/migrate_db_engine.js +++ b/scripts/migrate_db_engine.js @@ -25,7 +25,7 @@ const { Template, User, VoiceState, - Webhook, + Webhook } = require("../../dist/entities/index"); async function main() { @@ -54,7 +54,7 @@ async function main() { VoiceState, Webhook, Message, - Attachment, + Attachment ]; const oldDB = await initDatabase(); @@ -69,7 +69,7 @@ async function main() { database: isSqlite ? process.env.TO : undefined, entities, name: "new", - synchronize: true, + synchronize: true }); let i = 0; diff --git a/scripts/rights.js b/scripts/rights.js index 20fd139c7..5ae576efd 100644 --- a/scripts/rights.js +++ b/scripts/rights.js @@ -6,20 +6,20 @@ const { argv, stdout, exit } = require("process"); const { execIn, getLines, parts } = require("./utils"); -let lines = fs.readFileSync(path.join(__dirname, "..", "src", "util", "util","Rights.ts")).toString() +let lines = fs.readFileSync(path.join(__dirname, "..", "src", "util", "util", "Rights.ts")).toString(); let lines2 = lines.split("\n"); -let lines3 = lines2.filter(y=>y.includes(": BitFlag(")); -let lines4 = lines3.map(x=>x.split("//")[0].trim()) +let lines3 = lines2.filter((y) => y.includes(": BitFlag(")); +let lines4 = lines3.map((x) => x.split("//")[0].trim()); function BitFlag(int) { - return 1n << eval(`${int}n`); + return 1n << BigInt(int); } -let rights = [] +let rights = []; let maxRights = 0n; -lines4.forEach(x=>{ - maxRights += eval(`rights.${x.replace(':'," = ").replace(",",";")}`) -}) +lines4.forEach((x) => { + maxRights += eval(`rights.${x.replace(":", " = ").replace(",", ";")}`); +}); //max rights... console.log(`Maximum rights: ${maxRights}`); //discord rights... @@ -31,4 +31,4 @@ discordRights -= rights.BYPASS_RATE_LIMITS; discordRights -= rights.ADD_MEMBERS; discordRights -= rights.MANAGE_RATE_LIMITS; discordRights -= rights.OPERATOR; -console.log(`Discord-like rights: ${discordRights}`); \ No newline at end of file +console.log(`Discord-like rights: ${discordRights}`); diff --git a/scripts/update_schemas.js b/scripts/update_schemas.js index 361bedc13..151b52d25 100644 --- a/scripts/update_schemas.js +++ b/scripts/update_schemas.js @@ -6,4 +6,4 @@ const { argv, stdout, exit } = require("process"); const { execIn, getLines, parts } = require("./utils"); -execIn("node scripts/generate_schema.js", path.join('.')); \ No newline at end of file +execIn("node scripts/generate_schema.js", path.join(".")); diff --git a/scripts/utils.js b/scripts/utils.js index 84aaeed61..b679392b9 100644 --- a/scripts/utils.js +++ b/scripts/utils.js @@ -4,6 +4,8 @@ const { env } = require("process"); const { execSync } = require("child_process"); const { argv, stdout, exit } = require("process"); +const projectRoot = path.resolve(path.join(__dirname, "..")); + function copyRecursiveSync(src, dest) { //if (verbose) console.log(`cpsync: ${src} -> ${dest}`); let exists = fs.existsSync(src); @@ -16,10 +18,7 @@ function copyRecursiveSync(src, dest) { if (isDirectory) { fs.mkdirSync(dest, { recursive: true }); fs.readdirSync(src).forEach(function (childItemName) { - copyRecursiveSync( - path.join(src, childItemName), - path.join(dest, childItemName) - ); + copyRecursiveSync(path.join(src, childItemName), path.join(dest, childItemName)); }); } else { fs.copyFileSync(src, dest); @@ -44,8 +43,45 @@ function getLines(output) { return output.split("\n").length; } -module.exports = { +function getDirs(dir) { + return fs.readdirSync(dir).filter((x) => { + try { + fs.readdirSync(dir.join(dir, x)); + return true; + } catch (e) { + return false; + } + }); +} + +function walk(dir) { + let results = []; + let list = fs.readdirSync(dir); + list.forEach(function (file) { + file = dir + "/" + file; + let stat = fs.statSync(file); + if (stat && stat.isDirectory()) { + /* Recurse into a subdirectory */ + results = results.concat(walk(file)); + } else { + results.push(file); + } + }); + return results; +} + +function sanitizeVarName(str) { + return str.replace("-", "_").replace(/[^\w\s]/gi, ""); +} + +module.exports = { //consts + projectRoot, //functions - copyRecursiveSync, execIn, getLines + copyRecursiveSync, + execIn, + getLines, + getDirs, + walk, + sanitizeVarName }; diff --git a/tests/cdn_endpoints.test.js b/tests/cdn_endpoints.test.js index 5a543e54a..5627bf40e 100644 --- a/tests/cdn_endpoints.test.js +++ b/tests/cdn_endpoints.test.js @@ -11,17 +11,12 @@ if (!process.env.STORAGE_PROVIDER) process.env.STORAGE_PROVIDER = "file"; if (process.env.STORAGE_PROVIDER === "file") { if (process.env.STORAGE_LOCATION) { if (!process.env.STORAGE_LOCATION.startsWith("/")) { - process.env.STORAGE_LOCATION = path.join( - __dirname, - "..", - process.env.STORAGE_LOCATION, - "/" - ); + process.env.STORAGE_LOCATION = path.join(__dirname, "..", process.env.STORAGE_LOCATION, "/"); } } else { process.env.STORAGE_LOCATION = path.join(__dirname, "..", "files", "/"); } - if(!fs.existsSync(process.env.STORAGE_LOCATION)) fs.mkdirSync(process.env.STORAGE_LOCATION, {recursive:true}); + if (!fs.existsSync(process.env.STORAGE_LOCATION)) fs.mkdirSync(process.env.STORAGE_LOCATION, { recursive: true }); } const { CDNServer } = require("../dist/Server"); const { Config } = require("@fosscord/util"); @@ -59,9 +54,7 @@ describe("/attachments", () => { }); describe("with signature specified, without file specified", () => { test("route should respond with 400", async () => { - const response = await request - .post("/attachments/123456789") - .set({ signature: Config.get().security.requestSignature }); + const response = await request.post("/attachments/123456789").set({ signature: Config.get().security.requestSignature }); expect(response.statusCode).toBe(400); }); }); @@ -72,9 +65,7 @@ describe("/attachments", () => { .set({ signature: Config.get().security.requestSignature }) .attach("file", __dirname + "/antman.jpg"); expect(response.statusCode).toBe(200); - expect(response.headers["content-type"]).toEqual( - expect.stringContaining("json") - ); + expect(response.headers["content-type"]).toEqual(expect.stringContaining("json")); expect(response.body.url).toBeDefined(); }); }); @@ -86,11 +77,9 @@ describe("/attachments", () => { .post("/attachments/123456789") .set({ signature: Config.get().security.requestSignature }) .attach("file", __dirname + "/antman.jpg"); - request - .get(response.body.url.replace("http://localhost:3003", "")) - .then((x) => { - expect(x.statusCode).toBe(200); - }); + request.get(response.body.url.replace("http://localhost:3003", "")).then((x) => { + expect(x.statusCode).toBe(200); + }); }); }); }); @@ -101,13 +90,9 @@ describe("/attachments", () => { .post("/attachments/123456789") .set({ signature: Config.get().security.requestSignature }) .attach("file", __dirname + "/antman.jpg"); - request - .delete( - response.body.url.replace("http://localhost:3003", "") - ) - .then((x) => { - expect(x.body.success).toBeDefined(); - }); + request.delete(response.body.url.replace("http://localhost:3003", "")).then((x) => { + expect(x.body.success).toBeDefined(); + }); }); }); }); @@ -123,9 +108,7 @@ describe("/avatars", () => { }); describe("with signature specified, without file specified", () => { test("route should respond with 400", async () => { - const response = await request - .post("/avatars/123456789") - .set({ signature: Config.get().security.requestSignature }); + const response = await request.post("/avatars/123456789").set({ signature: Config.get().security.requestSignature }); expect(response.statusCode).toBe(400); }); }); @@ -136,9 +119,7 @@ describe("/avatars", () => { .set({ signature: Config.get().security.requestSignature }) .attach("file", __dirname + "/antman.jpg"); expect(response.statusCode).toBe(200); - expect(response.headers["content-type"]).toEqual( - expect.stringContaining("json") - ); + expect(response.headers["content-type"]).toEqual(expect.stringContaining("json")); expect(response.body.url).toBeDefined(); }); }); @@ -150,11 +131,9 @@ describe("/avatars", () => { .post("/avatars/123456789") .set({ signature: Config.get().security.requestSignature }) .attach("file", __dirname + "/antman.jpg"); - request - .get(response.body.url.replace("http://localhost:3003", "")) - .then((x) => { - expect(x.statusCode).toBe(200); - }); + request.get(response.body.url.replace("http://localhost:3003", "")).then((x) => { + expect(x.statusCode).toBe(200); + }); }); }); }); @@ -165,13 +144,9 @@ describe("/avatars", () => { .post("/avatars/123456789") .set({ signature: Config.get().security.requestSignature }) .attach("file", __dirname + "/antman.jpg"); - request - .delete( - response.body.url.replace("http://localhost:3003", "") - ) - .then((x) => { - expect(x.body.success).toBeDefined(); - }); + request.delete(response.body.url.replace("http://localhost:3003", "")).then((x) => { + expect(x.body.success).toBeDefined(); + }); }); }); }); @@ -187,35 +162,25 @@ describe("/external", () => { }); describe("with signature specified, without file specified", () => { test("route should respond with 400", async () => { - const response = await request - .post("/external") - .set({ signature: Config.get().security.requestSignature }); + const response = await request.post("/external").set({ signature: Config.get().security.requestSignature }); expect(response.statusCode).toBe(400); }); }); describe("with signature specified, with file specified ", () => { test("route should respond with Content-type: application/json, 200 and res.body.url", async () => { - const response = await request - .post("/external") - .set({ signature: Config.get().security.requestSignature }) - .send({ - url: "https://i.ytimg.com/vi_webp/TiXzhQr5AUc/mqdefault.webp", - }); + const response = await request.post("/external").set({ signature: Config.get().security.requestSignature }).send({ + url: "https://i.ytimg.com/vi_webp/TiXzhQr5AUc/mqdefault.webp" + }); expect(response.statusCode).toBe(200); - expect(response.headers["content-type"]).toEqual( - expect.stringContaining("json") - ); + expect(response.headers["content-type"]).toEqual(expect.stringContaining("json")); expect(response.body.id).toBeDefined(); }); }); describe("with signature specified, with falsy url specified ", () => { test("route should respond with 400", async () => { - const response = await request - .post("/external") - .set({ signature: Config.get().security.requestSignature }) - .send({ - url: "notavalidurl.123", - }); + const response = await request.post("/external").set({ signature: Config.get().security.requestSignature }).send({ + url: "notavalidurl.123" + }); expect(response.statusCode).toBe(400); }); }); @@ -223,12 +188,9 @@ describe("/external", () => { describe("GET", () => { describe("getting uploaded image by url returned by POST /avatars", () => { test("route should respond with 200", async () => { - let response = await request - .post("/external") - .set({ signature: Config.get().security.requestSignature }) - .send({ - url: "https://i.ytimg.com/vi_webp/TiXzhQr5AUc/mqdefault.webp", - }); + let response = await request.post("/external").set({ signature: Config.get().security.requestSignature }).send({ + url: "https://i.ytimg.com/vi_webp/TiXzhQr5AUc/mqdefault.webp" + }); request.get(`external/${response.body.id}`).then((x) => { expect(x.statusCode).toBe(200); }); diff --git a/tests/routes.test.ts b/tests/routes.test.ts index c915fab9b..51c068b5a 100644 --- a/tests/routes.test.ts +++ b/tests/routes.test.ts @@ -1,13 +1,13 @@ // TODO: check every route based on route() parameters: https://github.com/fosscord/fosscord-server/issues/308 // TODO: check every route with different database engine -import getRouteDescriptions from "../jest/getRouteDescriptions"; -import { join } from "path"; -import fs from "fs"; +import { Channel, Event, events, Guild, User } from "@fosscord/util"; import Ajv from "ajv"; import addFormats from "ajv-formats"; +import fs from "fs"; import fetch from "node-fetch"; -import { Event, User, events, Guild, Channel } from "@fosscord/util"; +import { join } from "path"; +import getRouteDescriptions from "../jest/getRouteDescriptions"; const SchemaPath = join(__dirname, "..", "assets", "schemas.json"); const schemas = JSON.parse(fs.readFileSync(SchemaPath, { encoding: "utf8" })); diff --git a/tests/setupJest.js b/tests/setupJest.js index 378d72d51..bb52525f5 100644 --- a/tests/setupJest.js +++ b/tests/setupJest.js @@ -17,7 +17,7 @@ global.expect.extend({ return { pass: time < target && !error, - message: () => error || `${func.name} took ${time}ms of maximum ${target}`, + message: () => error || `${func.name} took ${time}ms of maximum ${target}` }; - }, + } }); diff --git a/tsconfig.json b/tsconfig.json index b9e17f299..eb3399aad 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,85 +1,79 @@ -{ - "include": ["src/**/*.ts"], - "exclude": [], - "compilerOptions": { - - /* Basic Options */ - "incremental": false /* Enable incremental compilation */, - "target": "ESNext" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */, - "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */, - "lib": [ - "ESNext" - ] /* Specify library files to be included in the compilation. */, - "allowJs": true /* Allow javascript files to be compiled. */, - "checkJs": true /* Report errors in .js files. */, - // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ - "declaration": false /* Generates corresponding '.d.ts' file. */, - "declarationMap": false /* Generates a sourcemap for each corresponding '.d.ts' file. */, - "sourceMap": true /* Generates corresponding '.map' file. */, - // "outFile": "./", /* Concatenate and emit output to single file. */ - "outDir": "./dist/" /* Redirect output structure to the directory. */, - "rootDir": "./src/" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */, - // "composite": true, /* Enable project compilation */ - // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ - // "removeComments": true, /* Do not emit comments to output. */ - // "noEmit": true, /* Do not emit outputs. */ - // "importHelpers": true, /* Import emit helpers from 'tslib'. */ - // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ - // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ - - /* Strict Type-Checking Options */ - "strict": true /* Enable all strict type-checking options. */, - "noImplicitAny": true /* Raise error on expressions and declarations with an implied 'any' type. */, - "strictNullChecks": true /* Enable strict null checks. */, - // "strictFunctionTypes": true, /* Enable strict checking of function types. */ - // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ - "strictPropertyInitialization": false /* Enable strict checking of property initialization in classes. */, - // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ - "alwaysStrict": true /* Parse in strict mode and emit "use strict" for each source file. */, - - /* Additional Checks */ - // "noUnusedLocals": true, /* Report errors on unused locals. */ - // "noUnusedParameters": true, /* Report errors on unused parameters. */ - // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ - // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ - - /* Module Resolution Options */ - "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ - // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ - // "typeRoots": [], /* List of folders to include type definitions from. */ - "types": [ - "node" - ] /* Type declaration files to be included in compilation. */, - // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ - "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, - // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ - // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ - - /* Source Map Options */ - // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ - // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ - // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ - // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ - - /* Experimental Options */ - // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ - // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ - - /* Advanced Options */ - "skipLibCheck": true /* Skip type checking of declaration files. */, - "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */, - "emitDecoratorMetadata": true, - "experimentalDecorators": true, - "resolveJsonModule": true, - "baseUrl": "./src/", - "paths": { - "@fosscord/api": ["./api/index"], - "@fosscord/gateway": ["./gateway/index"], - "@fosscord/cdn": ["./cdn/index"], - "@fosscord/util": ["./util/index"] - }, - "plugins": [{ "transform": "@ovos-media/ts-transform-paths" }], - "noEmitHelpers": true, - "importHelpers": true - } -} +{ + "include": ["src/**/*.ts"], + "exclude": [], + "compilerOptions": { + /* Basic Options */ + "incremental": false /* Enable incremental compilation */, + "target": "ESNext" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */, + "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */, + "lib": ["ESNext"] /* Specify library files to be included in the compilation. */, + "allowJs": true /* Allow javascript files to be compiled. */, + "checkJs": true /* Report errors in .js files. */, + // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ + "declaration": false /* Generates corresponding '.d.ts' file. */, + "declarationMap": false /* Generates a sourcemap for each corresponding '.d.ts' file. */, + "sourceMap": true /* Generates corresponding '.map' file. */, + // "outFile": "./", /* Concatenate and emit output to single file. */ + "outDir": "./dist/" /* Redirect output structure to the directory. */, + "rootDir": "./src/" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */, + // "composite": true, /* Enable project compilation */ + // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ + // "removeComments": true, /* Do not emit comments to output. */ + // "noEmit": true, /* Do not emit outputs. */ + // "importHelpers": true, /* Import emit helpers from 'tslib'. */ + // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ + // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ + + /* Strict Type-Checking Options */ + "strict": true /* Enable all strict type-checking options. */, + "noImplicitAny": true /* Raise error on expressions and declarations with an implied 'any' type. */, + "strictNullChecks": true /* Enable strict null checks. */, + // "strictFunctionTypes": true, /* Enable strict checking of function types. */ + // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ + "strictPropertyInitialization": false /* Enable strict checking of property initialization in classes. */, + // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ + "alwaysStrict": true /* Parse in strict mode and emit "use strict" for each source file. */, + + /* Additional Checks */ + // "noUnusedLocals": true, /* Report errors on unused locals. */ + // "noUnusedParameters": true, /* Report errors on unused parameters. */ + // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + + /* Module Resolution Options */ + "moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */, + // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ + // "typeRoots": [], /* List of folders to include type definitions from. */ + "types": ["node"] /* Type declaration files to be included in compilation. */, + // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ + "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, + // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + + /* Source Map Options */ + // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ + // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ + + /* Experimental Options */ + // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ + // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ + + /* Advanced Options */ + "skipLibCheck": true /* Skip type checking of declaration files. */, + "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "resolveJsonModule": true, + "baseUrl": "./src/", + "paths": { + "@fosscord/api": ["./api/index"], + "@fosscord/gateway": ["./gateway/index"], + "@fosscord/cdn": ["./cdn/index"], + "@fosscord/util": ["./util/index"] + }, + "noEmitHelpers": true, + "importHelpers": true + } +}