diff --git a/.eslintrc b/.eslintrc index 6f04225bd0..ae13cce26b 100644 --- a/.eslintrc +++ b/.eslintrc @@ -25,6 +25,7 @@ "rules": { "eqeqeq": 2, "curly": 2, + "no-console": "error", "arrow-body-style": ["error", "as-needed"], "spaced-comment": "error", "object-shorthand": "error", diff --git a/app/components/EventListItem.tsx b/app/components/EventListItem.tsx index aeb27de61b..713b518ec5 100644 --- a/app/components/EventListItem.tsx +++ b/app/components/EventListItem.tsx @@ -25,6 +25,7 @@ import Item, { Actions } from "~/components/List/Item"; import Time from "~/components/Time"; import useStores from "~/hooks/useStores"; import RevisionMenu from "~/menus/RevisionMenu"; +import Logger from "~/utils/Logger"; import { documentHistoryUrl } from "~/utils/routeHelpers"; type Props = { @@ -109,7 +110,7 @@ const EventListItem = ({ event, latest, document, ...rest }: Props) => { break; default: - console.warn("Unhandled event: ", event.name); + Logger.warn("Unhandled event", { event }); } if (!meta) { diff --git a/app/editor/components/FloatingToolbar.tsx b/app/editor/components/FloatingToolbar.tsx index 6b4752cc36..38f453f359 100644 --- a/app/editor/components/FloatingToolbar.tsx +++ b/app/editor/components/FloatingToolbar.tsx @@ -8,6 +8,7 @@ import useComponentSize from "~/hooks/useComponentSize"; import useEventListener from "~/hooks/useEventListener"; import useMediaQuery from "~/hooks/useMediaQuery"; import useViewportHeight from "~/hooks/useViewportHeight"; +import Logger from "~/utils/Logger"; import { useEditor } from "./EditorContext"; type Props = { @@ -63,7 +64,7 @@ function usePosition({ fromPos = view.coordsAtPos(selection.from); toPos = view.coordsAtPos(selection.to, -1); } catch (err) { - console.warn(err); + Logger.warn("Unable to calculate selection position", err); return defaultPosition; } diff --git a/app/editor/components/LinkEditor.tsx b/app/editor/components/LinkEditor.tsx index 1c9a24d887..af744ea362 100644 --- a/app/editor/components/LinkEditor.tsx +++ b/app/editor/components/LinkEditor.tsx @@ -17,6 +17,7 @@ import { ResizingHeightContainer } from "~/components/ResizingHeightContainer"; import Scrollable from "~/components/Scrollable"; import { Dictionary } from "~/hooks/useDictionary"; import { ToastOptions } from "~/types"; +import Logger from "~/utils/Logger"; import Input from "./Input"; import LinkSearchResult from "./LinkSearchResult"; import ToolbarButton from "./ToolbarButton"; @@ -223,8 +224,8 @@ class LinkEditor extends React.Component { }, previousValue: trimmedValue, })); - } catch (error) { - console.error(error); + } catch (err) { + Logger.error("Error searching for link", err); } } }; diff --git a/app/editor/components/SuggestionsMenu.tsx b/app/editor/components/SuggestionsMenu.tsx index 743f59e2b3..df334f86dd 100644 --- a/app/editor/components/SuggestionsMenu.tsx +++ b/app/editor/components/SuggestionsMenu.tsx @@ -16,6 +16,7 @@ import { Portal } from "~/components/Portal"; import Scrollable from "~/components/Scrollable"; import useDictionary from "~/hooks/useDictionary"; import useToasts from "~/hooks/useToasts"; +import Logger from "~/utils/Logger"; import { useEditor } from "./EditorContext"; import Input from "./Input"; @@ -99,7 +100,7 @@ function SuggestionsMenu(props: Props) { fromPos = view.coordsAtPos(selection.from); toPos = view.coordsAtPos(selection.to, -1); } catch (err) { - console.warn(err); + Logger.warn("Unable to calculate caret position", err); return { top: 0, bottom: 0, diff --git a/app/models/BaseModel.ts b/app/models/BaseModel.ts index d423a728cf..6811399a24 100644 --- a/app/models/BaseModel.ts +++ b/app/models/BaseModel.ts @@ -1,5 +1,6 @@ import { pick } from "lodash"; import { set, observable } from "mobx"; +import Logger from "~/utils/Logger"; import { getFieldsForModel } from "./decorators/Field"; export default abstract class BaseModel { @@ -126,7 +127,7 @@ export default abstract class BaseModel { const attributes = this.toAPI(); if (Object.keys(attributes).length === 0) { - console.warn("Checking dirty on model with no @Field decorators"); + Logger.warn("Checking dirty on model with no @Field decorators"); } return ( diff --git a/app/scenes/CollectionPermissions/AddGroupsToCollection.tsx b/app/scenes/CollectionPermissions/AddGroupsToCollection.tsx index 4ff29053fe..7869a5c341 100644 --- a/app/scenes/CollectionPermissions/AddGroupsToCollection.tsx +++ b/app/scenes/CollectionPermissions/AddGroupsToCollection.tsx @@ -78,7 +78,6 @@ function AddGroupsToCollection(props: Props) { toasts.showToast(t("Could not add user"), { type: "error", }); - console.error(err); } }; diff --git a/app/utils/Logger.ts b/app/utils/Logger.ts index 3571213160..fc4991929d 100644 --- a/app/utils/Logger.ts +++ b/app/utils/Logger.ts @@ -1,3 +1,4 @@ +/* eslint-disable no-console */ import * as Sentry from "@sentry/react"; import env from "~/env"; diff --git a/build.js b/build.js index 3c2e4b88dc..a15857a8c5 100755 --- a/build.js +++ b/build.js @@ -1,3 +1,4 @@ +/* eslint-disable no-console */ /* eslint-disable @typescript-eslint/no-var-requires */ /* eslint-disable no-undef */ const { exec } = require("child_process"); diff --git a/server/.eslintrc b/server/.eslintrc index f5aad6b0e0..b334ec6dbc 100644 --- a/server/.eslintrc +++ b/server/.eslintrc @@ -2,6 +2,14 @@ "extends": [ "../.eslintrc" ], + "overrides": [ + { + "files": ["scripts/*"], + "rules": { + "no-console": "off" + } + } + ], "env": { "jest": true, "node": true diff --git a/server/logging/Logger.ts b/server/logging/Logger.ts index 5d0527b6bc..64ef4c0208 100644 --- a/server/logging/Logger.ts +++ b/server/logging/Logger.ts @@ -1,3 +1,4 @@ +/* eslint-disable no-console */ import { IncomingMessage } from "http"; import chalk from "chalk"; import { isEmpty, isArray, isObject, isString } from "lodash"; diff --git a/server/logging/sentry.ts b/server/logging/sentry.ts index a89221d0dc..25585a5d33 100644 --- a/server/logging/sentry.ts +++ b/server/logging/sentry.ts @@ -32,9 +32,6 @@ if (env.SENTRY_DSN) { export function requestErrorHandler(error: any, ctx: AppContext) { // we don't need to report every time a request stops to the bug tracker if (error.code === "EPIPE" || error.code === "ECONNRESET") { - console.warn("Connection error", { - error, - }); return; } @@ -69,6 +66,7 @@ export function requestErrorHandler(error: any, ctx: AppContext) { Sentry.captureException(error); }); } else { + // eslint-disable-next-line no-console console.error(error); } } diff --git a/server/models/decorators/Deprecated.ts b/server/models/decorators/Deprecated.ts index b3ac0f8611..68f6c64f3e 100644 --- a/server/models/decorators/Deprecated.ts +++ b/server/models/decorators/Deprecated.ts @@ -1,11 +1,12 @@ /* eslint-disable @typescript-eslint/ban-types */ +import Logger from "@server/logging/Logger"; const Deprecated = (message?: string) => ( target: Object, propertyKey: string ) => { if (process.env[propertyKey]) { - console.warn( + Logger.warn( `The environment variable ${propertyKey} is deprecated and will be removed in a future release. ${message}` ); } diff --git a/server/utils/readManifestFile.ts b/server/utils/readManifestFile.ts index 64f0d152ba..72826f3038 100644 --- a/server/utils/readManifestFile.ts +++ b/server/utils/readManifestFile.ts @@ -1,5 +1,6 @@ import fs from "fs"; import path from "path"; +import Logger from "@server/logging/Logger"; export type Chunk = { file: string; @@ -17,7 +18,7 @@ export const readManifestFile = (file = "./build/app/manifest.json") => { try { manifest = fs.readFileSync(absoluteFilePath, "utf8") as string; } catch (err) { - console.warn( + Logger.warn( `Can not find ${absoluteFilePath}. Try executing "yarn vite:build" before running in production mode.` ); } diff --git a/shared/editor/commands/insertFiles.ts b/shared/editor/commands/insertFiles.ts index 78d512445a..f8289d681f 100644 --- a/shared/editor/commands/insertFiles.ts +++ b/shared/editor/commands/insertFiles.ts @@ -1,4 +1,5 @@ import * as Sentry from "@sentry/react"; +import invariant from "invariant"; import { NodeSelection } from "prosemirror-state"; import { EditorView } from "prosemirror-view"; import { v4 as uuidv4 } from "uuid"; @@ -43,10 +44,10 @@ const insertFiles = function ( onShowToast, } = options; - if (!uploadFile) { - console.warn("uploadFile callback must be defined to handle uploads."); - return; - } + invariant( + uploadFile, + "uploadFile callback must be defined to handle uploads." + ); // okay, we have some dropped files and a handler – lets stop this // event going any further up the stack diff --git a/shared/editor/extensions/Mermaid.ts b/shared/editor/extensions/Mermaid.ts index 24c98184a0..2e3a9de06b 100644 --- a/shared/editor/extensions/Mermaid.ts +++ b/shared/editor/extensions/Mermaid.ts @@ -85,7 +85,6 @@ function getNewState({ } ); } catch (error) { - console.log(error); const errorNode = document.getElementById( "d" + "mermaid-diagram-" + diagramId ); diff --git a/shared/editor/extensions/Suggestion.tsx b/shared/editor/extensions/Suggestion.tsx index 40a3c52cf6..3a26664dd2 100644 --- a/shared/editor/extensions/Suggestion.tsx +++ b/shared/editor/extensions/Suggestion.tsx @@ -12,30 +12,26 @@ export default class Suggestion extends Extension { return [new SuggestionsMenuPlugin(this.editor, this.options)]; } - inputRules = (_options: { type: NodeType; schema: Schema }) => { - console.log(this.name, this.options.openRegex); - - return [ - new InputRule(this.options.openRegex, (state, match) => { - if ( - match && - state.selection.$from.parent.type.name === "paragraph" && - (!isInCode(state) || this.options.enabledInCode) && - (!isInTable(state) || this.options.enabledInTable) - ) { - this.editor.events.emit(EventType.SuggestionsMenuOpen, { - type: this.options.type, - query: match[1], - }); - } - return null; - }), - new InputRule(this.options.closeRegex, (state, match) => { - if (match) { - this.editor.events.emit(EventType.SuggestionsMenuClose); - } - return null; - }), - ]; - }; + inputRules = (_options: { type: NodeType; schema: Schema }) => [ + new InputRule(this.options.openRegex, (state, match) => { + if ( + match && + state.selection.$from.parent.type.name === "paragraph" && + (!isInCode(state) || this.options.enabledInCode) && + (!isInTable(state) || this.options.enabledInTable) + ) { + this.editor.events.emit(EventType.SuggestionsMenuOpen, { + type: this.options.type, + query: match[1], + }); + } + return null; + }), + new InputRule(this.options.closeRegex, (state, match) => { + if (match) { + this.editor.events.emit(EventType.SuggestionsMenuClose); + } + return null; + }), + ]; } diff --git a/shared/editor/marks/Mark.ts b/shared/editor/marks/Mark.ts index 97a5f44c15..8d55dcccf3 100644 --- a/shared/editor/marks/Mark.ts +++ b/shared/editor/marks/Mark.ts @@ -31,8 +31,8 @@ export default abstract class Mark extends Extension { return []; } - toMarkdown(state: MarkdownSerializerState, node: ProsemirrorNode) { - console.error("toMarkdown not implemented", state, node); + toMarkdown(_state: MarkdownSerializerState, _node: ProsemirrorNode) { + throw new Error("toMarkdown not implemented"); } parseMarkdown(): TokenConfig | void { diff --git a/shared/editor/nodes/Node.ts b/shared/editor/nodes/Node.ts index cc0e49b1e4..11dd755b59 100644 --- a/shared/editor/nodes/Node.ts +++ b/shared/editor/nodes/Node.ts @@ -37,8 +37,8 @@ export default abstract class Node extends Extension { return {}; } - toMarkdown(state: MarkdownSerializerState, node: ProsemirrorNode): void { - console.error("toMarkdown not implemented", state, node); + toMarkdown(_state: MarkdownSerializerState, _node: ProsemirrorNode) { + throw new Error("toMarkdown not implemented"); } parseMarkdown(): TokenConfig | void {