Merge pull request #4686 from thelounge/decoupleServer

Decouple server
This commit is contained in:
Max Leiter 2023-02-26 17:20:20 -08:00 committed by GitHub
commit c6a202d6ab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 92 additions and 90 deletions

View File

@ -7,6 +7,7 @@ const projects = defineConfig({
"./tsconfig.json", "./tsconfig.json",
"./client/tsconfig.json", "./client/tsconfig.json",
"./server/tsconfig.json", "./server/tsconfig.json",
"./shared/tsconfig.json",
"./test/tsconfig.json", "./test/tsconfig.json",
], ],
}, },

View File

@ -19,7 +19,7 @@
<script lang="ts"> <script lang="ts">
import {computed, defineComponent, PropType, ref} from "vue"; import {computed, defineComponent, PropType, ref} from "vue";
import constants from "../js/constants"; import {condensedTypes} from "../../shared/irc";
import {ClientMessage, ClientNetwork} from "../js/types"; import {ClientMessage, ClientNetwork} from "../js/types";
import Message from "./Message.vue"; import Message from "./Message.vue";
@ -51,7 +51,7 @@ export default defineComponent({
const condensedText = computed(() => { const condensedText = computed(() => {
const obj: Record<string, number> = {}; const obj: Record<string, number> = {};
constants.condensedTypes.forEach((type) => { condensedTypes.forEach((type) => {
obj[type] = 0; obj[type] = 0;
}); });
@ -75,7 +75,7 @@ export default defineComponent({
obj.part += obj.quit; obj.part += obj.quit;
const strings: string[] = []; const strings: string[] = [];
constants.condensedTypes.forEach((type) => { condensedTypes.forEach((type) => {
if (obj[type]) { if (obj[type]) {
switch (type) { switch (type) {
case "chghost": case "chghost":

View File

@ -58,7 +58,7 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import constants from "../js/constants"; import {condensedTypes} from "../../shared/irc";
import eventbus from "../js/eventbus"; import eventbus from "../js/eventbus";
import clipboard from "../js/clipboard"; import clipboard from "../js/clipboard";
import socket from "../js/socket"; import socket from "../js/socket";
@ -184,7 +184,7 @@ export default defineComponent({
// If actions are hidden, just return a message list with them excluded // If actions are hidden, just return a message list with them excluded
if (store.state.settings.statusMessages === "hidden") { if (store.state.settings.statusMessages === "hidden") {
return props.channel.messages.filter( return props.channel.messages.filter(
(message) => !constants.condensedTypes.has(message.type) (message) => !condensedTypes.has(message.type)
); );
} }
@ -200,11 +200,7 @@ export default defineComponent({
for (const message of props.channel.messages) { for (const message of props.channel.messages) {
// If this message is not condensable, or its an action affecting our user, // If this message is not condensable, or its an action affecting our user,
// then just append the message to container and be done with it // then just append the message to container and be done with it
if ( if (message.self || message.highlight || !condensedTypes.has(message.type)) {
message.self ||
message.highlight ||
!constants.condensedTypes.has(message.type)
) {
lastCondensedContainer = null; lastCondensedContainer = null;
condensed.push(message); condensed.push(message);

View File

@ -17,18 +17,6 @@ const colorCodeMap = [
["15", "Light Grey"], ["15", "Light Grey"],
]; ];
const condensedTypes = new Set([
"away",
"back",
"chghost",
"join",
"kick",
"mode",
"nick",
"part",
"quit",
]);
const timeFormats = { const timeFormats = {
msgDefault: "HH:mm", msgDefault: "HH:mm",
msgWithSeconds: "HH:mm:ss", msgWithSeconds: "HH:mm:ss",
@ -39,7 +27,6 @@ const timeFormats = {
export default { export default {
colorCodeMap, colorCodeMap,
commands: [] as string[], commands: [] as string[],
condensedTypes,
timeFormats, timeFormats,
// Same value as media query in CSS that forces sidebars to become overlays // Same value as media query in CSS that forces sidebars to become overlays
mobileViewportPixels: 768, mobileViewportPixels: 768,

View File

@ -1,4 +0,0 @@
const matchFormatting =
/\x02|\x1D|\x1F|\x16|\x0F|\x11|\x1E|\x03(?:[0-9]{1,2}(?:,[0-9]{1,2})?)?|\x04(?:[0-9a-f]{6}(?:,[0-9a-f]{6})?)?/gi;
export default (message: string) => message.replace(matchFormatting, "").trim();

View File

@ -2,7 +2,7 @@ import anyIntersection from "./anyIntersection";
import fill from "./fill"; import fill from "./fill";
import {ChannelPart} from "./findChannels"; import {ChannelPart} from "./findChannels";
import {EmojiPart} from "./findEmoji"; import {EmojiPart} from "./findEmoji";
import {LinkPart} from "./findLinks"; import {LinkPart} from "../../../../shared/linkify";
import {NamePart} from "./findNames"; import {NamePart} from "./findNames";
export type Part = { export type Part = {

View File

@ -3,11 +3,11 @@
import {h as createElement, VNode} from "vue"; import {h as createElement, VNode} from "vue";
import parseStyle from "./ircmessageparser/parseStyle"; import parseStyle from "./ircmessageparser/parseStyle";
import findChannels, {ChannelPart} from "./ircmessageparser/findChannels"; import findChannels from "./ircmessageparser/findChannels";
import {findLinks, LinkPart} from "./ircmessageparser/findLinks"; import {findLinks} from "../../../shared/linkify";
import findEmoji, {EmojiPart} from "./ircmessageparser/findEmoji"; import findEmoji from "./ircmessageparser/findEmoji";
import findNames, {NamePart} from "./ircmessageparser/findNames"; import findNames from "./ircmessageparser/findNames";
import merge, {MergedParts, Part} from "./ircmessageparser/merge"; import merge, {MergedParts} from "./ircmessageparser/merge";
import emojiMap from "./fullnamemap.json"; import emojiMap from "./fullnamemap.json";
import LinkPreviewToggle from "../../components/LinkPreviewToggle.vue"; import LinkPreviewToggle from "../../components/LinkPreviewToggle.vue";
import LinkPreviewFileSize from "../../components/LinkPreviewFileSize.vue"; import LinkPreviewFileSize from "../../components/LinkPreviewFileSize.vue";

View File

@ -1,6 +1,6 @@
/* eslint-disable @typescript-eslint/restrict-plus-operands */ /* eslint-disable @typescript-eslint/restrict-plus-operands */
import socket from "../socket"; import socket from "../socket";
import cleanIrcMessage from "../helpers/ircmessageparser/cleanIrcMessage"; import {cleanIrcMessage} from "../../../shared/irc";
import {store} from "../store"; import {store} from "../store";
import {switchToChannel} from "../router"; import {switchToChannel} from "../router";
import {ClientChan, ClientMention, ClientMessage, NetChan} from "../types"; import {ClientChan, ClientMention, ClientMessage, NetChan} from "../types";

View File

@ -1,7 +1,8 @@
{ {
"extends": "../tsconfig.base.json" /* Path to base configuration file to inherit from. Requires TypeScript version 2.1 or later. */, "extends": "../tsconfig.base.json" /* Path to base configuration file to inherit from. Requires TypeScript version 2.1 or later. */,
"include": [ "include": [
"./**/*" "./**/*",
"../shared"
] /* Specifies a list of glob patterns that match files to be included in compilation. If no 'files' or 'include' property is present in a tsconfig.json, the compiler defaults to including all files in the containing directory and subdirectories except those specified by 'exclude'. Requires TypeScript version 2.0 or later. */, ] /* Specifies a list of glob patterns that match files to be included in compilation. If no 'files' or 'include' property is present in a tsconfig.json, the compiler defaults to including all files in the containing directory and subdirectories except those specified by 'exclude'. Requires TypeScript version 2.0 or later. */,
"files": [ "files": [
"../package.json", "../package.json",

View File

@ -9,7 +9,7 @@ import log from "./log";
import Chan, {Channel, ChanType} from "./models/chan"; import Chan, {Channel, ChanType} from "./models/chan";
import Msg, {MessageType, UserInMessage} from "./models/msg"; import Msg, {MessageType, UserInMessage} from "./models/msg";
import Config from "./config"; import Config from "./config";
import constants from "../client/js/constants"; import {condensedTypes} from "../shared/irc";
import inputs from "./plugins/inputs"; import inputs from "./plugins/inputs";
import PublicClient from "./plugins/packages/publicClient"; import PublicClient from "./plugins/packages/publicClient";
@ -569,7 +569,7 @@ class Client {
startIndex--; startIndex--;
// Do not count condensed messages towards the 100 messages // Do not count condensed messages towards the 100 messages
if (constants.condensedTypes.has(chan.messages[i].type)) { if (condensedTypes.has(chan.messages[i].type)) {
continue; continue;
} }

View File

@ -5,7 +5,7 @@ import mime from "mime-types";
import log from "../../log"; import log from "../../log";
import Config from "../../config"; import Config from "../../config";
import {findLinksWithSchema} from "../../../client/js/helpers/ircmessageparser/findLinks"; import {findLinksWithSchema} from "../../../shared/linkify";
import storage from "../storage"; import storage from "../storage";
import Client from "../../client"; import Client from "../../client";
import Chan from "../../models/chan"; import Chan from "../../models/chan";

View File

@ -1,6 +1,6 @@
import Msg, {MessageType} from "../../models/msg"; import Msg, {MessageType} from "../../models/msg";
import LinkPrefetch from "./link"; import LinkPrefetch from "./link";
import cleanIrcMessage from "../../../client/js/helpers/ircmessageparser/cleanIrcMessage"; import {cleanIrcMessage} from "../../../shared/irc";
import Helper from "../../helper"; import Helper from "../../helper";
import {IrcEventHandler} from "../../client"; import {IrcEventHandler} from "../../client";
import Chan, {ChanType} from "../../models/chan"; import Chan, {ChanType} from "../../models/chan";

View File

@ -2,10 +2,9 @@
"extends": "../tsconfig.base.json" /* Path to base configuration file to inherit from. Requires TypeScript version 2.1 or later. */, "extends": "../tsconfig.base.json" /* Path to base configuration file to inherit from. Requires TypeScript version 2.1 or later. */,
"include": [ "include": [
"**/*", "**/*",
"../client/js/helpers/ircmessageparser/*.ts" "../shared/"
] /* Specifies a list of glob patterns that match files to be included in compilation. If no 'files' or 'include' property is present in a tsconfig.json, the compiler defaults to including all files in the containing directory and subdirectories except those specified by 'exclude'. Requires TypeScript version 2.0 or later. */, ] /* Specifies a list of glob patterns that match files to be included in compilation. If no 'files' or 'include' property is present in a tsconfig.json, the compiler defaults to including all files in the containing directory and subdirectories except those specified by 'exclude'. Requires TypeScript version 2.0 or later. */,
"files": [ "files": [
"../client/js/constants.ts",
"../babel.config.cjs", "../babel.config.cjs",
"../defaults/config.js", "../defaults/config.js",
"../package.json", "../package.json",
@ -15,13 +14,8 @@
"files": true "files": true
}, },
"compilerOptions": { "compilerOptions": {
"outDir": "../dist" /* Specify an output folder for all emitted files. See more: https://www.typescriptlang.org/tsconfig#outDir */,
"noEmit": false /* Disable emitting file from a compilation. See more: https://www.typescriptlang.org/tsconfig#noEmit */, "noEmit": false /* Disable emitting file from a compilation. See more: https://www.typescriptlang.org/tsconfig#noEmit */,
// TODO: Remove eventually // TODO: Remove eventually
"noImplicitAny": false /*Enable error reporting for expressions and declarations with an implied any type. See more: https://www.typescriptlang.org/tsconfig#noImplicitAny */ "noImplicitAny": false /*Enable error reporting for expressions and declarations with an implied any type. See more: https://www.typescriptlang.org/tsconfig#noImplicitAny */
} /* Instructs the TypeScript compiler how to compile .ts files. */, } /* Instructs the TypeScript compiler how to compile .ts files. */
"exclude": [
"./dist"
] /* Specifies a list of glob patterns that match files to be excluded from compilation. Requires TypeScript version 2.0 or later. */
} }

18
shared/irc.ts Normal file
View File

@ -0,0 +1,18 @@
const matchFormatting =
/\x02|\x1D|\x1F|\x16|\x0F|\x11|\x1E|\x03(?:[0-9]{1,2}(?:,[0-9]{1,2})?)?|\x04(?:[0-9a-f]{6}(?:,[0-9a-f]{6})?)?/gi;
export function cleanIrcMessage(message: string) {
return message.replace(matchFormatting, "").trim();
}
export const condensedTypes = new Set([
"away",
"back",
"chghost",
"join",
"kick",
"mode",
"nick",
"part",
"quit",
]);

View File

@ -1,15 +1,19 @@
import LinkifyIt, {Match} from "linkify-it"; import LinkifyIt, {Match} from "linkify-it";
import {Part} from "./merge"; import tlds from "tlds";
export type LinkPart = Part & { export type NoSchemaMatch = Match & {
noschema: boolean;
};
export type LinkPart = {
start: number;
end: number;
link: string; link: string;
}; };
type OurMatch = Match & { LinkifyIt.prototype.normalize = function normalize(match: NoSchemaMatch) {
noschema?: boolean; match.noschema = false;
};
LinkifyIt.prototype.normalize = function normalize(match: OurMatch) {
if (!match.schema) { if (!match.schema) {
match.schema = "http:"; match.schema = "http:";
match.url = "http://" + match.url; match.url = "http://" + match.url;
@ -27,7 +31,6 @@ LinkifyIt.prototype.normalize = function normalize(match: OurMatch) {
} }
}; };
import tlds from "tlds";
const linkify = LinkifyIt().tlds(tlds).tlds("onion", true); const linkify = LinkifyIt().tlds(tlds).tlds("onion", true);
// Known schemes to detect in text // Known schemes to detect in text
@ -52,32 +55,30 @@ for (const schema of commonSchemes) {
linkify.add(schema + ":", "http:"); linkify.add(schema + ":", "http:");
} }
function findLinks(text: string) { export function findLinks(text: string) {
const matches = linkify.match(text) as OurMatch[]; const matches = linkify.match(text) as NoSchemaMatch[];
if (!matches) { if (!matches) {
return []; return [];
} }
return matches.map(returnUrl); return matches.map(makeLinkPart);
} }
function findLinksWithSchema(text: string) { export function findLinksWithSchema(text: string) {
const matches = linkify.match(text) as OurMatch[]; const matches = linkify.match(text) as NoSchemaMatch[];
if (!matches) { if (!matches) {
return []; return [];
} }
return matches.filter((url) => !url.noschema).map(returnUrl); return matches.filter((url) => !url.noschema).map(makeLinkPart);
} }
function returnUrl(url: OurMatch): LinkPart { function makeLinkPart(url: NoSchemaMatch): LinkPart {
return { return {
start: url.index, start: url.index,
end: url.lastIndex, end: url.lastIndex,
link: url.url, link: url.url,
}; };
} }
export {findLinks, findLinksWithSchema};

13
shared/tsconfig.json Normal file
View File

@ -0,0 +1,13 @@
{
"extends": "../tsconfig.base.json" /* Path to base configuration file to inherit from. Requires TypeScript version 2.1 or later. */,
"include": [
"*"
] /* Specifies a list of glob patterns that match files to be included in compilation. If no 'files' or 'include' property is present in a tsconfig.json, the compiler defaults to including all files in the containing directory and subdirectories except those specified by 'exclude'. Requires TypeScript version 2.0 or later. */,
"files": [] /* If no 'files' or 'include' property is present in a tsconfig.json, the compiler defaults to including all files in the containing directory and subdirectories except those specified by 'exclude'. When a 'files' property is specified, only those files and those specified by 'include' are included. */,
"ts-node": {
"files": true
},
"compilerOptions": {
"noEmit": false /* Disable emitting file from a compilation. See more: https://www.typescriptlang.org/tsconfig#noEmit */
}
}

View File

@ -18,19 +18,6 @@ describe("client-side constants", function () {
}); });
}); });
describe(".condensedTypes", function () {
it("should be a non-empty array", function () {
expect(constants.condensedTypes).to.be.an.instanceof(Set).that.is.not.empty;
});
it("should only contain ASCII strings", function () {
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'type' implicitly has an 'any' type.
constants.condensedTypes.forEach((type) => {
expect(type).to.be.a("string").that.does.match(/^\w+$/);
});
});
});
describe(".timeFormats", function () { describe(".timeFormats", function () {
it("should be objects of strings", function () { it("should be objects of strings", function () {
expect(constants.timeFormats.msgDefault).to.be.an("string").that.is.not.empty; expect(constants.timeFormats.msgDefault).to.be.an("string").that.is.not.empty;

View File

@ -1,5 +1,5 @@
import {expect} from "chai"; import {expect} from "chai";
import cleanIrcMessage from "../../../../../client/js/helpers/ircmessageparser/cleanIrcMessage"; import {cleanIrcMessage} from "../../shared/irc";
describe("cleanIrcMessage", function () { describe("cleanIrcMessage", function () {
it("should remove all formatting", function () { it("should remove all formatting", function () {

View File

@ -1,8 +1,5 @@
import {expect} from "chai"; import {expect} from "chai";
import { import {findLinks, findLinksWithSchema} from "../../shared/linkify";
findLinks,
findLinksWithSchema,
} from "../../../../../client/js/helpers/ircmessageparser/findLinks";
describe("findLinks", () => { describe("findLinks", () => {
it("should find url", () => { it("should find url", () => {

14
test/shared/irc.ts Normal file
View File

@ -0,0 +1,14 @@
import {expect} from "chai";
import {condensedTypes} from "../../shared/irc";
describe(".condensedTypes", function () {
it("should be a non-empty array", function () {
expect(condensedTypes).to.be.an.instanceof(Set).that.is.not.empty;
});
it("should only contain ASCII strings", function () {
condensedTypes.forEach((type) => {
expect(type).to.be.a("string").that.does.match(/^\w+$/);
});
});
});

View File

@ -3,7 +3,8 @@
"include": [ "include": [
"**/*", "**/*",
"../client", "../client",
"../server" "../server",
"../shared"
] /* Specifies a list of glob patterns that match files to be included in compilation. If no 'files' or 'include' property is present in a tsconfig.json, the compiler defaults to including all files in the containing directory and subdirectories except those specified by 'exclude'. Requires TypeScript version 2.0 or later. */, ] /* Specifies a list of glob patterns that match files to be included in compilation. If no 'files' or 'include' property is present in a tsconfig.json, the compiler defaults to including all files in the containing directory and subdirectories except those specified by 'exclude'. Requires TypeScript version 2.0 or later. */,
"files": [ "files": [
"../babel.config.cjs", "../babel.config.cjs",

View File

@ -99,6 +99,5 @@
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
"skipLibCheck": true /* Skip type checking all .d.ts files. */ "skipLibCheck": true /* Skip type checking all .d.ts files. */
}, },
"files": ["./package.json", "./server/helper.ts"],
"exclude": ["./dist"] "exclude": ["./dist"]
} }

View File

@ -6,12 +6,9 @@
] /* If no 'files' or 'include' property is present in a tsconfig.json, the compiler defaults to including all files in the containing directory and subdirectories except those specified by 'exclude'. When a 'files' property is specified, only those files and those specified by 'include' are included. */, ] /* If no 'files' or 'include' property is present in a tsconfig.json, the compiler defaults to including all files in the containing directory and subdirectories except those specified by 'exclude'. When a 'files' property is specified, only those files and those specified by 'include' are included. */,
// "exclude": [], // "exclude": [],
"references": [ "references": [
{ {"path": "./client"},
"path": "./client" /* Path to referenced tsconfig or to folder containing tsconfig. */ {"path": "./server"},
}, {"path": "./shared"}
{
"path": "./server" /* Path to referenced tsconfig or to folder containing tsconfig. */
}
] /* Referenced projects. Requires TypeScript version 3.0 or later. */, ] /* Referenced projects. Requires TypeScript version 3.0 or later. */,
"compilerOptions": { "compilerOptions": {
// TODO: Remove eventually // TODO: Remove eventually

View File

@ -58,7 +58,7 @@ const config: webpack.Configuration = {
}, },
{ {
test: /\.ts$/i, test: /\.ts$/i,
include: [path.resolve(__dirname, "client")], include: [path.resolve(__dirname, "client"), path.resolve(__dirname, "shared")],
exclude: path.resolve(__dirname, "node_modules"), exclude: path.resolve(__dirname, "node_modules"),
use: { use: {
loader: "babel-loader", loader: "babel-loader",