[chore] Fix grammar, add JSDocs
| @@ -4,17 +4,21 @@ dataRoot: ./data | ||
| 4 | 4 | # -- SERVER CONFIGURATION -- |
| 5 | 5 | # Listen for incoming connections |
| 6 | 6 | listen: false |
| 7 | 7 | # Enables IPv6 and/or IPv4 protocols. Need to have at least one enabled! |
| 8 | 8 | protocol: |
| 9 | 9 | ipv4: true |
| 10 | 10 | ipv6: false |
| 11 | 11 | # Prefers IPv6 for dns, you should probablyDNS. enableEnable this on ISPs that don't have issues with IPv6 |
| 12 | 12 | dnsPreferIPv6: false |
| 13 | -# the hostname that autorun opens probably best left on auto. use options like 'localhost', 'st.example.com' | |
| 13 | +# The hostname that autorun opens. | |
| 14 | +# - Use "auto" to let the server decide | |
| 15 | +# - Use options like 'localhost', 'st.example.com' | |
| 14 | 16 | autorunHostname: "auto" |
| 15 | 17 | # Server port |
| 16 | 18 | port: 8000 |
| 17 | -# overrides the port for autorun with open your browser with this port and ignore what port the server is running on. -1 is use server port | |
| 19 | +# Overrides the port for autorun in browser. | |
| 20 | +# - Use -1 to use the server port. | |
| 21 | +# - Specify a port to override the default. | |
| 18 | 22 | autorunPortOverride: -1 |
| 19 | 23 | # -- SECURITY CONFIGURATION -- |
| 20 | 24 | # Toggle whitelist mode |
| @@ -43,6 +43,8 @@ const { | ||
| 43 | 43 | getConfigValue, |
| 44 | 44 | color, |
| 45 | 45 | forwardFetchResponse, |
| 46 | + removeColorFormatting, | |
| 47 | + getSeparator, | |
| 46 | 48 | } = require('./src/util'); |
| 47 | 49 | const { ensureThumbnailCache } = require('./src/endpoints/thumbnails'); |
| 48 | 50 | |
| @@ -54,10 +56,6 @@ if (process.versions && process.versions.node && process.versions.node.match(/20 | ||
| 54 | 56 | if (net.setDefaultAutoSelectFamily) net.setDefaultAutoSelectFamily(false); |
| 55 | 57 | } |
| 56 | 58 | |
| 57 | - | |
| 58 | - | |
| 59 | - | |
| 60 | - | |
| 61 | 59 | const DEFAULT_PORT = 8000; |
| 62 | 60 | const DEFAULT_AUTORUN = false; |
| 63 | 61 | const DEFAULT_LISTEN = false; |
| @@ -618,7 +616,6 @@ const tavernUrl = new URL( | ||
| 618 | 616 | (':' + server_port), |
| 619 | 617 | ); |
| 620 | 618 | |
| 621 | - | |
| 622 | 619 | /** |
| 623 | 620 | * Tasks that need to be run before the server starts listening. |
| 624 | 621 | */ |
| @@ -667,19 +664,11 @@ const preSetupTasks = async function () { | ||
| 667 | 664 | }); |
| 668 | 665 | }; |
| 669 | 666 | |
| 670 | -function removeColorFormatting(text) { | |
| 667 | +/** | |
| 671 | - // ANSI escape codes for colors are usually in the format \x1b[<codes>m | |
| 668 | + * Gets the hostname to use for autorun in the browser. | |
| 672 | - return text.replace(/\x1b\[\d{1,2}(;\d{1,2})*m/g, ''); | |
| 669 | + * @returns {string} The hostname to use for autorun | |
| 673 | -} | |
| 670 | + */ | |
| 674 | - | |
| 675 | -function getSeparator(n) { | |
| 676 | - return '='.repeat(n); | |
| 677 | -} | |
| 678 | - | |
| 679 | - | |
| 680 | - | |
| 681 | 671 | function getAutorunHostname() { |
| 682 | - | |
| 683 | 672 | if (autorunHostname === 'auto') { |
| 684 | 673 | if (enableIPv6 && enableIPv4) { |
| 685 | 674 | if (avoidLocalhost) return '[::1]'; |
| @@ -698,13 +687,12 @@ function getAutorunHostname() { | ||
| 698 | 687 | return autorunHostname; |
| 699 | 688 | } |
| 700 | 689 | |
| 701 | - | |
| 702 | 690 | /** |
| 703 | 691 | * Tasks that need to be run after the server starts listening. |
| 692 | + * @param {boolean} v6Failed If the server failed to start on IPv6 | |
| 693 | + * @param {boolean} v4Failed If the server failed to start on IPv4 | |
| 704 | 694 | */ |
| 705 | 695 | const postSetupTasks = async function (v6Failed, v4Failed) { |
| 706 | - | |
| 707 | - | |
| 708 | 696 | const autorunUrl = new URL( |
| 709 | 697 | (cliArguments.ssl ? 'https://' : 'http://') + |
| 710 | 698 | (getAutorunHostname()) + |
| @@ -712,30 +700,24 @@ const postSetupTasks = async function (v6Failed, v4Failed) { | ||
| 712 | 700 | ((autorunPortOverride >= 0) ? autorunPortOverride : server_port), |
| 713 | 701 | ); |
| 714 | 702 | |
| 715 | - | |
| 716 | 703 | console.log('Launching...'); |
| 717 | 704 | |
| 718 | 705 | if (autorun) open(autorunUrl.toString()); |
| 719 | 706 | |
| 720 | 707 | setWindowTitle('SillyTavern WebServer'); |
| 721 | 708 | |
| 722 | - | |
| 723 | - let ipv6Color = color.green; | |
| 724 | - let ipv4Color = color.green; | |
| 725 | - let autorunColor = color.blue; | |
| 726 | - | |
| 727 | 709 | let logListen = 'SillyTavern is listening on'; |
| 728 | 710 | |
| 729 | 711 | if (enableIPv6 && !v6Failed) { |
| 730 | 712 | logListen += ipv6Colorcolor.green(' IPv6: ' + tavernUrlV6.host); |
| 731 | 713 | } |
| 732 | 714 | |
| 733 | 715 | if (enableIPv4 && !v4Failed) { |
| 734 | 716 | logListen += ipv4Colorcolor.green(' IPv4: ' + tavernUrl.host); |
| 735 | 717 | } |
| 736 | 718 | |
| 737 | 719 | letconst goToLog = 'Go to: ' + autorunColorcolor.blue(autorunUrl) + ' to open SillyTavern'; |
| 738 | 720 | letconst plainGoToLog = removeColorFormatting(goToLog); |
| 739 | 721 | |
| 740 | 722 | console.log(logListen); |
| 741 | 723 | console.log('\n' + getSeparator(plainGoToLog.length) + '\n'); |
| @@ -798,8 +780,11 @@ function logSecurityAlert(message) { | ||
| 798 | 780 | process.exit(1); |
| 799 | 781 | } |
| 800 | 782 | |
| 801 | - | |
| 783 | +/** | |
| 802 | - | |
| 784 | + * Handles the case where the server failed to start on one or both protocols. | |
| 785 | + * @param {boolean} v6Failed If the server failed to start on IPv6 | |
| 786 | + * @param {boolean} v4Failed If the server failed to start on IPv4 | |
| 787 | + */ | |
| 803 | 788 | function handleServerListenFail(v6Failed, v4Failed) { |
| 804 | 789 | if (v6Failed && !enableIPv4) { |
| 805 | 790 | console.error('fatal error: Failed to start server on IPv6 and IPv4 disabled'); |
| @@ -817,7 +802,12 @@ function handleServerListenFail(v6Failed, v4Failed) { | ||
| 817 | 802 | } |
| 818 | 803 | } |
| 819 | 804 | |
| 820 | - | |
| 805 | +/** | |
| 806 | + * Creates an HTTPS server. | |
| 807 | + * @param {URL} url The URL to listen on | |
| 808 | + * @returns {Promise<void>} A promise that resolves when the server is listening | |
| 809 | + * @throws {Error} If the server fails to start | |
| 810 | + */ | |
| 821 | 811 | function createHttpsServer(url) { |
| 822 | 812 | return new Promise((resolve, reject) => { |
| 823 | 813 | const server = https.createServer( |
| @@ -831,6 +821,12 @@ function createHttpsServer(url) { | ||
| 831 | 821 | }); |
| 832 | 822 | } |
| 833 | 823 | |
| 824 | +/** | |
| 825 | + * Creates an HTTP server. | |
| 826 | + * @param {URL} url The URL to listen on | |
| 827 | + * @returns {Promise<void>} A promise that resolves when the server is listening | |
| 828 | + * @throws {Error} If the server fails to start | |
| 829 | + */ | |
| 834 | 830 | function createHttpServer(url) { |
| 835 | 831 | return new Promise((resolve, reject) => { |
| 836 | 832 | const server = http.createServer(app); |
| @@ -840,22 +836,16 @@ function createHttpServer(url) { | ||
| 840 | 836 | }); |
| 841 | 837 | } |
| 842 | 838 | |
| 843 | - | |
| 844 | - | |
| 845 | - | |
| 846 | 839 | async function startHTTPorHTTPS() { |
| 847 | 840 | let v6Failed = false; |
| 848 | 841 | let v4Failed = false; |
| 849 | 842 | |
| 850 | 843 | letconst createFunc = cliArguments.ssl ? createHttpsServer : createHttpServer; |
| 851 | - if (cliArguments.ssl) { | |
| 852 | - createFunc = createHttpsServer; | |
| 853 | - } | |
| 854 | 844 | |
| 855 | 845 | if (enableIPv6) { |
| 856 | 846 | try { |
| 857 | 847 | await createFunc(tavernUrlV6); |
| 858 | 848 | } catch (error) { |
| 859 | 849 | if (enableIPv4) { |
| 860 | 850 | console.error('non-fatal error: failed to start server on IPv6', error); |
| 861 | 851 | } |
| @@ -867,7 +857,7 @@ async function startHTTPorHTTPS() { | ||
| 867 | 857 | if (enableIPv4) { |
| 868 | 858 | try { |
| 869 | 859 | await createFunc(tavernUrl); |
| 870 | 860 | } catch (error) { |
| 871 | 861 | if (enableIPv6) { |
| 872 | 862 | console.error('non-fatal error: failed to start server on IPv4', error); |
| 873 | 863 | } |
| @@ -875,25 +865,17 @@ async function startHTTPorHTTPS() { | ||
| 875 | 865 | v4Failed = true; |
| 876 | 866 | } |
| 877 | 867 | } |
| 868 | + | |
| 878 | 869 | return [v6Failed, v4Failed]; |
| 879 | 870 | } |
| 880 | 871 | |
| 881 | - | |
| 882 | - | |
| 883 | - | |
| 884 | 872 | async function startServer() { |
| 885 | 873 | letconst [v6Failed, v4Failed] = falseawait startHTTPorHTTPS(); |
| 886 | - let v4Failed = false; | |
| 887 | - | |
| 888 | - | |
| 889 | - [v6Failed, v4Failed] = await startHTTPorHTTPS(); | |
| 890 | 874 | |
| 891 | 875 | handleServerListenFail(v6Failed, v4Failed); |
| 892 | 876 | postSetupTasks(v6Failed, v4Failed); |
| 893 | 877 | } |
| 894 | 878 | |
| 895 | - | |
| 896 | - | |
| 897 | 879 | async function verifySecuritySettings() { |
| 898 | 880 | // Skip all security checks as listen is set to false |
| 899 | 881 | if (!listen) { |
| @@ -627,6 +627,25 @@ class Cache { | ||
| 627 | 627 | } |
| 628 | 628 | } |
| 629 | 629 | |
| 630 | +/** | |
| 631 | + * Removes color formatting from a text string. | |
| 632 | + * @param {string} text Text with color formatting | |
| 633 | + * @returns {string} Text without color formatting | |
| 634 | + */ | |
| 635 | +function removeColorFormatting(text) { | |
| 636 | + // ANSI escape codes for colors are usually in the format \x1b[<codes>m | |
| 637 | + return text.replace(/\x1b\[\d{1,2}(;\d{1,2})*m/g, ''); | |
| 638 | +} | |
| 639 | + | |
| 640 | +/** | |
| 641 | + * Gets a separator string repeated n times. | |
| 642 | + * @param {number} n Number of times to repeat the separator | |
| 643 | + * @returns {string} Separator string | |
| 644 | + */ | |
| 645 | +function getSeparator(n) { | |
| 646 | + return '='.repeat(n); | |
| 647 | +} | |
| 648 | + | |
| 630 | 649 | module.exports = { |
| 631 | 650 | getConfig, |
| 632 | 651 | getConfigValue, |
| @@ -654,4 +673,6 @@ module.exports = { | ||
| 654 | 673 | trimV1, |
| 655 | 674 | Cache, |
| 656 | 675 | makeHttp2Request, |
| 676 | + removeColorFormatting, | |
| 677 | + getSeparator, | |
| 657 | 678 | }; |