From 6b965c06844e483c2892a5f3ef001a0be2083f34 Mon Sep 17 00:00:00 2001 From: Theo Browne Date: Wed, 15 Feb 2023 15:47:33 -0800 Subject: [PATCH 01/27] start logger --- apps/cli/cli-core/src/logger.ts | 3 +++ apps/cli/cli-core/src/trpc.ts | 17 +++++++++++++++++ apps/cli/cli-web/src/components/logs.tsx | 21 +++++++++++++++++++++ 3 files changed, 41 insertions(+) create mode 100644 apps/cli/cli-core/src/logger.ts create mode 100644 apps/cli/cli-web/src/components/logs.tsx diff --git a/apps/cli/cli-core/src/logger.ts b/apps/cli/cli-core/src/logger.ts new file mode 100644 index 00000000..910bc618 --- /dev/null +++ b/apps/cli/cli-core/src/logger.ts @@ -0,0 +1,3 @@ +export const Logger = { + subscribe: (inputFn: (m: { message: string }) => void) => null, +}; diff --git a/apps/cli/cli-core/src/trpc.ts b/apps/cli/cli-core/src/trpc.ts index ac9827b3..1a08a915 100644 --- a/apps/cli/cli-core/src/trpc.ts +++ b/apps/cli/cli-core/src/trpc.ts @@ -15,10 +15,27 @@ import { substituteTemplate } from "./templateSubstitution"; export type { ConfigValidatorType } from "./update-config"; +import { Logger } from "./logger"; +import { observable } from "@trpc/server/observable"; + export const t = initTRPC.create({ transformer: superjson, }); export const cliApiRouter = t.router({ + onLog: t.procedure.subscription(() => { + return observable<{ message: string }>((emit) => { + const onLog = (m: { message: string }) => { + emit.next(m); + }; + + Logger.subscribe(onLog); + + return () => { + // Logger.unsubscribe(onLog); + }; + }); + }), + getBlobs: t.procedure.query(async () => { if (!fs.existsSync(HOOK_PATH)) { // TODO: this should probably be an error, and the frontend should handle it diff --git a/apps/cli/cli-web/src/components/logs.tsx b/apps/cli/cli-web/src/components/logs.tsx new file mode 100644 index 00000000..00a826d9 --- /dev/null +++ b/apps/cli/cli-web/src/components/logs.tsx @@ -0,0 +1,21 @@ +import { useState } from "react"; +import { cliApi } from "../utils/api"; + +export const Logs = () => { + const [messages, setMessages] = useState([]); + cliApi.onLog.useSubscription(undefined, { + onData: (data) => { + setMessages((messages) => [...messages, data.message]); + }, + }); + + console.log(messages); + + return ( +
+ {messages.map((m) => ( + {m} + ))} +
+ ); +}; From 4df178c7ba6f8433567ef22db52048dbc3ebf224 Mon Sep 17 00:00:00 2001 From: "Mark R. Florkowski" Date: Wed, 15 Feb 2023 16:17:03 -0800 Subject: [PATCH 02/27] add logger package --- apps/cli/cli-core/package.json | 1 + apps/cli/cli-core/src/trpc.ts | 10 +++--- packages/logger/package.json | 23 ++++++++++++ packages/logger/src/index.ts | 66 ++++++++++++++++++++++++++++++++++ pnpm-lock.yaml | 14 ++++++++ 5 files changed, 110 insertions(+), 4 deletions(-) create mode 100644 packages/logger/package.json create mode 100644 packages/logger/src/index.ts diff --git a/apps/cli/cli-core/package.json b/apps/cli/cli-core/package.json index 99d78592..7db6983b 100644 --- a/apps/cli/cli-core/package.json +++ b/apps/cli/cli-core/package.json @@ -14,6 +14,7 @@ "format:check": "prettier --check --plugin-search-dir=. src/**/*.{cjs,mjs,ts,tsx,md,json} --ignore-path ../.gitignore" }, "dependencies": { + "@captain/logger": "workspace:*", "@trpc/client": "10.9.0", "@trpc/server": "10.9.0", "node-fetch": "^3.3.0", diff --git a/apps/cli/cli-core/src/trpc.ts b/apps/cli/cli-core/src/trpc.ts index 1a08a915..a7952ba3 100644 --- a/apps/cli/cli-core/src/trpc.ts +++ b/apps/cli/cli-core/src/trpc.ts @@ -15,23 +15,25 @@ import { substituteTemplate } from "./templateSubstitution"; export type { ConfigValidatorType } from "./update-config"; -import { Logger } from "./logger"; +import logger from "@captain/logger"; import { observable } from "@trpc/server/observable"; +import type { LogLevels } from "@captain/logger"; + export const t = initTRPC.create({ transformer: superjson, }); export const cliApiRouter = t.router({ onLog: t.procedure.subscription(() => { return observable<{ message: string }>((emit) => { - const onLog = (m: { message: string }) => { + const onLog = (m: { message: string; level: LogLevels }) => { emit.next(m); }; - Logger.subscribe(onLog); + logger.subscribe(onLog); return () => { - // Logger.unsubscribe(onLog); + logger.unsubscribe(onLog); }; }); }), diff --git a/packages/logger/package.json b/packages/logger/package.json new file mode 100644 index 00000000..fb335ead --- /dev/null +++ b/packages/logger/package.json @@ -0,0 +1,23 @@ +{ + "name": "@captain/logger", + "version": "0.0.1", + "main": "./src/index.ts", + "types": "./src/index.ts", + "license": "MIT", + "private": true, + "scripts": { + "clean": "rm -rf .turbo node_modules", + "typecheck": "tsc", + "lint": "eslint --ext .ts,tsx --ignore-path .gitignore src", + "lint:fix": "eslint --ext .ts,tsx --ignore-path .gitignore --fix src", + "format": "prettier --write --plugin-search-dir=. src/**/*.{cjs,mjs,ts,tsx,md,json} --ignore-path ../.gitignore", + "format:check": "prettier --check --plugin-search-dir=. src/**/*.{cjs,mjs,ts,tsx,md,json} --ignore-path ../.gitignore" + }, + "dependencies": {}, + "devDependencies": { + "@captain/tsconfig": "workspace:*", + "eslint": "^7.32.0", + "eslint-config-custom": "workspace:*", + "typescript": "^4.9.4" + } +} diff --git a/packages/logger/src/index.ts b/packages/logger/src/index.ts new file mode 100644 index 00000000..633fc309 --- /dev/null +++ b/packages/logger/src/index.ts @@ -0,0 +1,66 @@ +interface Logger { + trace(message: string, ...optionalParams: any[]): void; + debug(message: string, ...optionalParams: any[]): void; + info(message: string, ...optionalParams: any[]): void; + warn(message: string, ...optionalParams: any[]): void; + error(message: string, ...optionalParams: any[]): void; + [x: string]: any; +} + +export type LogLevels = "trace" | "debug" | "info" | "warn" | "error"; + +const prefixColors = { + trace: `\x1b[90m`, // gray + debug: `\x1b[36m`, // cyan + info: `\x1b[97m`, // white + warn: `\x1b[33m`, // yellow + error: `\x1b[31m`, // red +}; +const colorReset = `\x1b[0m`; + +class logger implements Logger { + private subscriptions: ((m: { message: string; level: LogLevels }) => void)[]; + + constructor() { + this.subscriptions = []; + } + + trace(message: string, ...optionalParams: any[]) { + this.log("trace", message, optionalParams); + } + + debug(message?: any, ...optionalParams: any[]) { + this.log("debug", message, optionalParams); + } + + info(message?: any, ...optionalParams: any[]) { + this.log("info", message, optionalParams); + } + + warn(message?: any, ...optionalParams: any[]) { + this.log("warn", message, optionalParams); + } + + error(message?: any, ...optionalParams: any[]) { + this.log("error", message, optionalParams); + } + + subscribe(fn: (m: { message: string; level: LogLevels }) => void) { + this.subscriptions.push(fn); + } + + unsubscribe(fn: (m: { message: string; level: LogLevels }) => void) { + this.subscriptions = this.subscriptions.filter((sub) => sub !== fn); + } + + private log(level: LogLevels, message: string, optionalParams: any[]) { + console[level]( + `${prefixColors[level]}[${level}] ${message}${colorReset}`, + ...optionalParams + ); + + this.subscriptions.forEach((sub) => sub({ message, level })); + } +} + +export default new logger(); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 198f34f4..0e03d352 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -70,6 +70,7 @@ importers: apps/cli/cli-core: specifiers: + '@captain/logger': workspace:* '@captain/tsconfig': workspace:* '@trpc/client': 10.9.0 '@trpc/server': 10.9.0 @@ -80,6 +81,7 @@ importers: typescript: ^4.9.4 zod: ^3.19.1 dependencies: + '@captain/logger': link:../../../packages/logger '@trpc/client': 10.9.0_@trpc+server@10.9.0 '@trpc/server': 10.9.0 node-fetch: 3.3.0 @@ -256,6 +258,18 @@ importers: eslint-plugin-react: 7.28.0 next: 13.1.5 + packages/logger: + specifiers: + '@captain/tsconfig': workspace:* + eslint: ^7.32.0 + eslint-config-custom: workspace:* + typescript: ^4.9.4 + devDependencies: + '@captain/tsconfig': link:../tsconfig + eslint: 7.32.0 + eslint-config-custom: link:../eslint-config-custom + typescript: 4.9.4 + packages/tailwind-config: specifiers: tailwindcss: ^3.2.4 From 25070eeba226aee25830a52ae8c86de50139674f Mon Sep 17 00:00:00 2001 From: "Mark R. Florkowski" Date: Wed, 15 Feb 2023 16:37:20 -0800 Subject: [PATCH 03/27] add web socket server --- apps/cli/cli-core/src/trpc.ts | 1 + apps/cli/cli/package.json | 4 +++- apps/cli/cli/src/index.ts | 3 ++- apps/cli/cli/src/server.ts | 35 ++++++++++++++++++++++++++++++----- pnpm-lock.yaml | 16 +++++++++++++--- 5 files changed, 49 insertions(+), 10 deletions(-) diff --git a/apps/cli/cli-core/src/trpc.ts b/apps/cli/cli-core/src/trpc.ts index a7952ba3..96b261a0 100644 --- a/apps/cli/cli-core/src/trpc.ts +++ b/apps/cli/cli-core/src/trpc.ts @@ -23,6 +23,7 @@ import type { LogLevels } from "@captain/logger"; export const t = initTRPC.create({ transformer: superjson, }); + export const cliApiRouter = t.router({ onLog: t.procedure.subscription(() => { return observable<{ message: string }>((emit) => { diff --git a/apps/cli/cli/package.json b/apps/cli/cli/package.json index b5d013b2..db058654 100644 --- a/apps/cli/cli/package.json +++ b/apps/cli/cli/package.json @@ -34,7 +34,8 @@ "fs-extra": "^11.1.0", "graceful-fs": "^4.2.10", "gradient-string": "^2.0.2", - "open": "^8.4.0" + "open": "^8.4.0", + "ws": "^8.12.1" }, "devDependencies": { "@captain/cli-web": "*", @@ -43,6 +44,7 @@ "@types/gradient-string": "^1.1.2", "@types/inquirer": "^9.0.2", "@types/node": "^18.8.0", + "@types/ws": "^8.5.4", "@vercel/ncc": "^0.36.0", "prettier": "^2.7.1", "prettier-plugin-tailwindcss": "^0.1.13", diff --git a/apps/cli/cli/src/index.ts b/apps/cli/cli/src/index.ts index 6b7fbe8a..2d6904cb 100644 --- a/apps/cli/cli/src/index.ts +++ b/apps/cli/cli/src/index.ts @@ -1,5 +1,5 @@ #!/usr/bin/env node -import { startServer } from "./server"; +import { startServer, startSocketServer } from "./server"; import { renderTitle } from "./utils/renderTitle"; const DOCS_LINK = "https://docs.webhookthing.com"; @@ -14,6 +14,7 @@ const main = async () => { ); await startServer(); + await startSocketServer(); }; main().catch((err) => { diff --git a/apps/cli/cli/src/server.ts b/apps/cli/cli/src/server.ts index 59acee25..83677b67 100644 --- a/apps/cli/cli/src/server.ts +++ b/apps/cli/cli/src/server.ts @@ -8,6 +8,9 @@ import { cliApiRouter } from "@captain/cli-core"; import { fastifyStatic } from "@fastify/static"; import path from "path"; +const PORT = 2033; +const WS_PORT = 2034; + const createServer = async () => { const server = fastify({ maxParamLength: 5000, @@ -47,18 +50,40 @@ import open from "open"; const openInBrowser = async () => { try { - await open("http://localhost:2033"); + await open(`http://localhost:${PORT}`); } catch (_err) { console.log("\x1b[31m[ERROR] Failed to open browser automatically\x1b[0m"); console.log( - `[INFO] You can still manually open the web UI here: http://localhost:2033` + `[INFO] You can still manually open the web UI here: http://localhost:${PORT}` ); } }; +import { applyWSSHandler } from "@trpc/server/adapters/ws"; +import ws from "ws"; + +export const startSocketServer = async () => { + const wss = new ws.Server({ + port: WS_PORT, + }); + const handler = applyWSSHandler({ wss, router: cliApiRouter }); + wss.on("connection", (ws) => { + console.log(`++ Connection (${wss.clients.size})`); + ws.once("close", () => { + console.log(`-- Connection (${wss.clients.size})`); + }); + }); + console.log(`[INFO] WebSocket Server listening on ws://localhost:${WS_PORT}`); + process.on("SIGTERM", () => { + console.log("SIGTERM"); + handler.broadcastReconnectNotification(); + wss.close(); + }); +}; + export const startServer = async () => { const server = await createServer(); - server.listen({ port: 2033 }, (err) => { + server.listen({ port: PORT }, (err) => { if (err) { console.error(err); process.exit(1); @@ -72,12 +97,12 @@ export const startServer = async () => { else if (!process.env.CI && !process.env.CODESPACES) { // Dont try to open the browser in CI, or on Codespaces, it will crash console.log( - `[INFO] Opening webhookthing at address: http://localhost:2033` + `[INFO] Opening webhookthing at address: http://localhost:${PORT}` ); void openInBrowser(); } else { console.log( - `[INFO] Running webhookthing at address: http://localhost:2033` + `[INFO] Running webhookthing at address: http://localhost:${PORT}` ); } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0e03d352..e38ccb0d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -31,6 +31,7 @@ importers: '@types/gradient-string': ^1.1.2 '@types/inquirer': ^9.0.2 '@types/node': ^18.8.0 + '@types/ws': ^8.5.4 '@vercel/ncc': ^0.36.0 fastify: ^4.11.0 fs-extra: ^11.1.0 @@ -42,6 +43,7 @@ importers: tsup: ^6.5.0 type-fest: ^3.0.0 typescript: ^4.9.4 + ws: ^8.12.1 dependencies: '@captain/cli-core': link:../cli-core '@fastify/cors': 8.2.0 @@ -53,6 +55,7 @@ importers: graceful-fs: 4.2.10 gradient-string: 2.0.2 open: 8.4.0 + ws: 8.12.1 devDependencies: '@captain/cli-web': link:../cli-web '@captain/tsconfig': link:../../../packages/tsconfig @@ -60,6 +63,7 @@ importers: '@types/gradient-string': 1.1.2 '@types/inquirer': 9.0.3 '@types/node': 18.11.18 + '@types/ws': 8.5.4 '@vercel/ncc': 0.36.1 prettier: 2.8.3 prettier-plugin-tailwindcss: 0.1.13_prettier@2.8.3 @@ -975,7 +979,7 @@ packages: resolution: {integrity: sha512-H8nwsmawFtKKRE6uhh1BtF1gQi/l147SmLsDGxB0HdYTHzjXz6uSQO3lEVmY7unKMzbArRjdoJQkEGpScszdSw==} dependencies: '@fastify/reply-from': 8.3.1 - ws: 8.12.0 + ws: 8.12.1 transitivePeerDependencies: - bufferutil - utf-8-validate @@ -1829,6 +1833,12 @@ packages: resolution: {integrity: sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==} dev: false + /@types/ws/8.5.4: + resolution: {integrity: sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg==} + dependencies: + '@types/node': 18.11.18 + dev: true + /@typescript-eslint/eslint-plugin/5.52.0_t6eclxjmd5f54roe4wwsj3rtvy: resolution: {integrity: sha512-lHazYdvYVsBokwCdKOppvYJKaJ4S41CgKBcPvyd0xjZNbvQdhn/pnJlGtQksQ/NhInzdaeaSarlBjDXHuclEbg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -7693,8 +7703,8 @@ packages: /wrappy/1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - /ws/8.12.0: - resolution: {integrity: sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig==} + /ws/8.12.1: + resolution: {integrity: sha512-1qo+M9Ba+xNhPB+YTWUlK6M17brTut5EXbcBaMRN5pH5dFrXz7lzz1ChFSUq3bOUl8yEvSenhHmYUNJxFzdJew==} engines: {node: '>=10.0.0'} peerDependencies: bufferutil: ^4.0.1 From 377f877cd151a2b78df352b5677b58c76a8a759f Mon Sep 17 00:00:00 2001 From: "Mark R. Florkowski" Date: Wed, 15 Feb 2023 16:59:10 -0800 Subject: [PATCH 04/27] support subscribing to different log levels --- packages/logger/src/index.ts | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/packages/logger/src/index.ts b/packages/logger/src/index.ts index 633fc309..9f6f28cb 100644 --- a/packages/logger/src/index.ts +++ b/packages/logger/src/index.ts @@ -7,7 +7,8 @@ interface Logger { [x: string]: any; } -export type LogLevels = "trace" | "debug" | "info" | "warn" | "error"; +const levels = ["trace", "debug", "info", "warn", "error"] as const; +export type LogLevels = (typeof levels)[number]; const prefixColors = { trace: `\x1b[90m`, // gray @@ -19,7 +20,10 @@ const prefixColors = { const colorReset = `\x1b[0m`; class logger implements Logger { - private subscriptions: ((m: { message: string; level: LogLevels }) => void)[]; + private subscriptions: { + fn: (m: { message: string; level: LogLevels }) => void; + level: LogLevels; + }[]; constructor() { this.subscriptions = []; @@ -45,12 +49,18 @@ class logger implements Logger { this.log("error", message, optionalParams); } - subscribe(fn: (m: { message: string; level: LogLevels }) => void) { - this.subscriptions.push(fn); + subscribe( + fn: (m: { message: string; level: LogLevels }) => void, + level?: LogLevels + ) { + if (!level) level = "info"; + this.subscriptions.push({ fn, level }); } unsubscribe(fn: (m: { message: string; level: LogLevels }) => void) { - this.subscriptions = this.subscriptions.filter((sub) => sub !== fn); + this.subscriptions = this.subscriptions.filter( + ({ fn: subFn }) => subFn !== fn + ); } private log(level: LogLevels, message: string, optionalParams: any[]) { @@ -59,8 +69,15 @@ class logger implements Logger { ...optionalParams ); - this.subscriptions.forEach((sub) => sub({ message, level })); + this.subscriptions.forEach(({ fn, level: subLevel }) => { + if (getLogLevels(subLevel).includes(level)) fn({ message, level }); + }); } } +// get all log levels above and including the given level +const getLogLevels = (level: LogLevels): LogLevels[] => { + return levels.slice(levels.indexOf(level)); +}; + export default new logger(); From a998a911fd4e09601098bd3be4d64418418708c7 Mon Sep 17 00:00:00 2001 From: "Mark R. Florkowski" Date: Wed, 15 Feb 2023 17:03:44 -0800 Subject: [PATCH 05/27] add ws to trpc client --- apps/cli/cli-web/src/utils/api-wrapper.tsx | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/apps/cli/cli-web/src/utils/api-wrapper.tsx b/apps/cli/cli-web/src/utils/api-wrapper.tsx index 4e009ef2..93c6cc94 100644 --- a/apps/cli/cli-web/src/utils/api-wrapper.tsx +++ b/apps/cli/cli-web/src/utils/api-wrapper.tsx @@ -1,10 +1,15 @@ -import { httpBatchLink } from "@trpc/client"; +import { createWSClient, httpBatchLink, wsLink } from "@trpc/client"; import superjson from "superjson"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { PropsWithChildren, useState } from "react"; import { cliApi } from "./api"; +// create persistent WebSocket connection +const wsClient = createWSClient({ + url: `ws://localhost:3001`, +}); + export const ApiTRPCProvider = (props: PropsWithChildren) => { const [queryClient] = useState(() => new QueryClient()); const [trpcClient] = useState(() => @@ -14,6 +19,9 @@ export const ApiTRPCProvider = (props: PropsWithChildren) => { httpBatchLink({ url: "http://localhost:2033/trpc", }), + wsLink({ + client: wsClient, + }), ], }) ); From caf1d8e6dfedb2ba755001e63a11774a03f64405 Mon Sep 17 00:00:00 2001 From: "Mark R. Florkowski" Date: Wed, 15 Feb 2023 17:05:38 -0800 Subject: [PATCH 06/27] remove old logger file --- apps/cli/cli-core/src/logger.ts | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 apps/cli/cli-core/src/logger.ts diff --git a/apps/cli/cli-core/src/logger.ts b/apps/cli/cli-core/src/logger.ts deleted file mode 100644 index 910bc618..00000000 --- a/apps/cli/cli-core/src/logger.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const Logger = { - subscribe: (inputFn: (m: { message: string }) => void) => null, -}; From 7f16cc85c1c7fb91ce84ee7d0ad87201ecabfb57 Mon Sep 17 00:00:00 2001 From: "Mark R. Florkowski" Date: Wed, 15 Feb 2023 17:22:04 -0800 Subject: [PATCH 07/27] misc cleanup, start testing --- apps/cli/cli-core/src/trpc.ts | 2 +- apps/cli/cli-web/src/App.tsx | 2 ++ apps/cli/cli-web/src/utils/api-wrapper.tsx | 4 +++- apps/cli/cli/src/server.ts | 6 ++++-- packages/logger/src/index.ts | 2 +- 5 files changed, 11 insertions(+), 5 deletions(-) diff --git a/apps/cli/cli-core/src/trpc.ts b/apps/cli/cli-core/src/trpc.ts index 96b261a0..1618dbde 100644 --- a/apps/cli/cli-core/src/trpc.ts +++ b/apps/cli/cli-core/src/trpc.ts @@ -128,7 +128,7 @@ export const cliApiRouter = t.router({ .mutation(async ({ input }) => { const { file, url } = input; let hasCustomConfig = false; - console.log(`[INFO] Reading file ${file}`); + logger.info(`Reading file ${file}`); let config = { url, diff --git a/apps/cli/cli-web/src/App.tsx b/apps/cli/cli-web/src/App.tsx index b6b6e4dd..4a67d806 100644 --- a/apps/cli/cli-web/src/App.tsx +++ b/apps/cli/cli-web/src/App.tsx @@ -4,6 +4,7 @@ import { Toaster } from "react-hot-toast"; import { JsonBlobs } from "./components/jsonblobs"; import { EndpointSetting } from "./components/endpointsetting"; import { useConnectionStateToasts } from "./utils/useConnectionStateToasts"; +import { Logs } from "./components/logs"; export default function Example() { useConnectionStateToasts(); @@ -47,6 +48,7 @@ export default function Example() {
+
diff --git a/apps/cli/cli-web/src/utils/api-wrapper.tsx b/apps/cli/cli-web/src/utils/api-wrapper.tsx index 93c6cc94..935b20a9 100644 --- a/apps/cli/cli-web/src/utils/api-wrapper.tsx +++ b/apps/cli/cli-web/src/utils/api-wrapper.tsx @@ -5,9 +5,11 @@ import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { PropsWithChildren, useState } from "react"; import { cliApi } from "./api"; +const WS_PORT = 2034; + // create persistent WebSocket connection const wsClient = createWSClient({ - url: `ws://localhost:3001`, + url: `ws://localhost:${WS_PORT}`, }); export const ApiTRPCProvider = (props: PropsWithChildren) => { diff --git a/apps/cli/cli/src/server.ts b/apps/cli/cli/src/server.ts index 83677b67..6b507cc4 100644 --- a/apps/cli/cli/src/server.ts +++ b/apps/cli/cli/src/server.ts @@ -68,9 +68,11 @@ export const startSocketServer = async () => { }); const handler = applyWSSHandler({ wss, router: cliApiRouter }); wss.on("connection", (ws) => { - console.log(`++ Connection (${wss.clients.size})`); + if (process.env.NODE_ENV === "development") + console.log(`Websocket Connection ++ (${wss.clients.size})`); ws.once("close", () => { - console.log(`-- Connection (${wss.clients.size})`); + if (process.env.NODE_ENV === "development") + console.log(`Websocket Connection -- (${wss.clients.size})`); }); }); console.log(`[INFO] WebSocket Server listening on ws://localhost:${WS_PORT}`); diff --git a/packages/logger/src/index.ts b/packages/logger/src/index.ts index 9f6f28cb..ade49e3c 100644 --- a/packages/logger/src/index.ts +++ b/packages/logger/src/index.ts @@ -65,7 +65,7 @@ class logger implements Logger { private log(level: LogLevels, message: string, optionalParams: any[]) { console[level]( - `${prefixColors[level]}[${level}] ${message}${colorReset}`, + `${prefixColors[level]}[${level.toUpperCase()}] ${message}${colorReset}`, ...optionalParams ); From b1e05f3ffa6e68fb7720475c9c4a257cd54a5887 Mon Sep 17 00:00:00 2001 From: Theo Browne Date: Wed, 15 Feb 2023 17:50:19 -0800 Subject: [PATCH 08/27] aaaaaaaaaaaa --- apps/cli/cli-core/src/trpc.ts | 4 +++- apps/cli/cli-web/src/components/logs.tsx | 7 +++++-- apps/cli/cli-web/src/utils/api-wrapper.tsx | 21 ++++++++++++++++----- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/apps/cli/cli-core/src/trpc.ts b/apps/cli/cli-core/src/trpc.ts index 1618dbde..306b704b 100644 --- a/apps/cli/cli-core/src/trpc.ts +++ b/apps/cli/cli-core/src/trpc.ts @@ -23,11 +23,13 @@ import type { LogLevels } from "@captain/logger"; export const t = initTRPC.create({ transformer: superjson, }); - export const cliApiRouter = t.router({ onLog: t.procedure.subscription(() => { + console.log("\n\n\n SUBBING NOW \n\n\n\n"); return observable<{ message: string }>((emit) => { + console.log("\n\n\n OBSERVABLE STARTING NOW \n\n\n\n"); const onLog = (m: { message: string; level: LogLevels }) => { + console.log("\n\n\n NEW MESSAGE RECEIVED \n\n\n\n"); emit.next(m); }; diff --git a/apps/cli/cli-web/src/components/logs.tsx b/apps/cli/cli-web/src/components/logs.tsx index 00a826d9..3fff0d86 100644 --- a/apps/cli/cli-web/src/components/logs.tsx +++ b/apps/cli/cli-web/src/components/logs.tsx @@ -5,11 +5,14 @@ export const Logs = () => { const [messages, setMessages] = useState([]); cliApi.onLog.useSubscription(undefined, { onData: (data) => { - setMessages((messages) => [...messages, data.message]); + console.log("new message received"); + setMessages((messages) => { + return [...messages, data.message]; + }); }, }); - console.log(messages); + console.log("messages", messages); return (
diff --git a/apps/cli/cli-web/src/utils/api-wrapper.tsx b/apps/cli/cli-web/src/utils/api-wrapper.tsx index 935b20a9..6b08be76 100644 --- a/apps/cli/cli-web/src/utils/api-wrapper.tsx +++ b/apps/cli/cli-web/src/utils/api-wrapper.tsx @@ -1,9 +1,8 @@ -import { createWSClient, httpBatchLink, wsLink } from "@trpc/client"; +import { createWSClient, httpBatchLink, splitLink, wsLink } from "@trpc/client"; import superjson from "superjson"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { PropsWithChildren, useState } from "react"; -import { cliApi } from "./api"; const WS_PORT = 2034; @@ -12,18 +11,30 @@ const wsClient = createWSClient({ url: `ws://localhost:${WS_PORT}`, }); +import { cliApi } from "./api"; + export const ApiTRPCProvider = (props: PropsWithChildren) => { const [queryClient] = useState(() => new QueryClient()); const [trpcClient] = useState(() => cliApi.createClient({ transformer: superjson, links: [ + splitLink({ + condition(op) { + console.log("operation?", op); + // check for context property `skipBatch` + return op.type === "subscription"; + }, + true: wsLink({ + client: wsClient, + }), + false: httpBatchLink({ + url: "http://localhost:2033/trpc", + }), + }), httpBatchLink({ url: "http://localhost:2033/trpc", }), - wsLink({ - client: wsClient, - }), ], }) ); From de64023b47156fb728ed41811225f589018a341d Mon Sep 17 00:00:00 2001 From: "Mark R. Florkowski" Date: Wed, 15 Feb 2023 22:47:16 -0800 Subject: [PATCH 09/27] add tsconfig --- packages/logger/tsconfig.json | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 packages/logger/tsconfig.json diff --git a/packages/logger/tsconfig.json b/packages/logger/tsconfig.json new file mode 100644 index 00000000..ded81f29 --- /dev/null +++ b/packages/logger/tsconfig.json @@ -0,0 +1,5 @@ +{ + "extends": "@captain/tsconfig/cli.json", + + "include": ["src", ".eslintrc.cjs"] +} From f97e5b560dc59e6a8904867e3860d80e4670d6e8 Mon Sep 17 00:00:00 2001 From: "Mark R. Florkowski" Date: Wed, 15 Feb 2023 22:50:36 -0800 Subject: [PATCH 10/27] add .gitignore --- packages/logger/.gitignore | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 packages/logger/.gitignore diff --git a/packages/logger/.gitignore b/packages/logger/.gitignore new file mode 100644 index 00000000..db204cc3 --- /dev/null +++ b/packages/logger/.gitignore @@ -0,0 +1,3 @@ +/dist + +node_modules \ No newline at end of file From b27a5ebb7ca5d21401c886863bb2a4821f6f5ec9 Mon Sep 17 00:00:00 2001 From: "Mark R. Florkowski" Date: Wed, 15 Feb 2023 23:09:12 -0800 Subject: [PATCH 11/27] lint --- apps/cli/cli/src/index.ts | 3 ++- apps/cli/cli/src/server.ts | 2 +- packages/logger/src/index.ts | 14 +++++++++----- packages/logger/tsconfig.json | 4 ++-- 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/apps/cli/cli/src/index.ts b/apps/cli/cli/src/index.ts index 2d6904cb..5ddb53d1 100644 --- a/apps/cli/cli/src/index.ts +++ b/apps/cli/cli/src/index.ts @@ -13,8 +13,9 @@ const main = async () => { `Questions? Check out the docs: ${DOCS_LINK}` ); + startSocketServer(); + await startServer(); - await startSocketServer(); }; main().catch((err) => { diff --git a/apps/cli/cli/src/server.ts b/apps/cli/cli/src/server.ts index 6b507cc4..d9f3be3b 100644 --- a/apps/cli/cli/src/server.ts +++ b/apps/cli/cli/src/server.ts @@ -62,7 +62,7 @@ const openInBrowser = async () => { import { applyWSSHandler } from "@trpc/server/adapters/ws"; import ws from "ws"; -export const startSocketServer = async () => { +export const startSocketServer = () => { const wss = new ws.Server({ port: WS_PORT, }); diff --git a/packages/logger/src/index.ts b/packages/logger/src/index.ts index ade49e3c..766760cc 100644 --- a/packages/logger/src/index.ts +++ b/packages/logger/src/index.ts @@ -1,3 +1,5 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +/* eslint-disable @typescript-eslint/no-unsafe-argument */ interface Logger { trace(message: string, ...optionalParams: any[]): void; debug(message: string, ...optionalParams: any[]): void; @@ -33,19 +35,19 @@ class logger implements Logger { this.log("trace", message, optionalParams); } - debug(message?: any, ...optionalParams: any[]) { + debug(message: string, ...optionalParams: any[]) { this.log("debug", message, optionalParams); } - info(message?: any, ...optionalParams: any[]) { + info(message: string, ...optionalParams: any[]) { this.log("info", message, optionalParams); } - warn(message?: any, ...optionalParams: any[]) { + warn(message: string, ...optionalParams: any[]) { this.log("warn", message, optionalParams); } - error(message?: any, ...optionalParams: any[]) { + error(message: string, ...optionalParams: any[]) { this.log("error", message, optionalParams); } @@ -80,4 +82,6 @@ const getLogLevels = (level: LogLevels): LogLevels[] => { return levels.slice(levels.indexOf(level)); }; -export default new logger(); +const loggerInstance = new logger(); + +export default loggerInstance; diff --git a/packages/logger/tsconfig.json b/packages/logger/tsconfig.json index ded81f29..51dc7ca5 100644 --- a/packages/logger/tsconfig.json +++ b/packages/logger/tsconfig.json @@ -1,5 +1,5 @@ { "extends": "@captain/tsconfig/cli.json", - - "include": ["src", ".eslintrc.cjs"] + "include": ["**/*.ts", "**/*.tsx"], + "exclude": ["node_modules"] } From ce4cd2482ece51b6d08ee9712ca5ecce3441737c Mon Sep 17 00:00:00 2001 From: "Mark R. Florkowski" Date: Thu, 16 Feb 2023 11:57:26 -0800 Subject: [PATCH 12/27] misc cleanup, close server on SIGTERM --- apps/cli/cli-core/src/trpc.ts | 5 +---- apps/cli/cli-web/src/components/logs.tsx | 4 ++-- apps/cli/cli/src/server.ts | 5 +++-- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/apps/cli/cli-core/src/trpc.ts b/apps/cli/cli-core/src/trpc.ts index 306b704b..4ce350d5 100644 --- a/apps/cli/cli-core/src/trpc.ts +++ b/apps/cli/cli-core/src/trpc.ts @@ -25,11 +25,8 @@ export const t = initTRPC.create({ }); export const cliApiRouter = t.router({ onLog: t.procedure.subscription(() => { - console.log("\n\n\n SUBBING NOW \n\n\n\n"); - return observable<{ message: string }>((emit) => { - console.log("\n\n\n OBSERVABLE STARTING NOW \n\n\n\n"); + return observable<{ message: string; level: LogLevels }>((emit) => { const onLog = (m: { message: string; level: LogLevels }) => { - console.log("\n\n\n NEW MESSAGE RECEIVED \n\n\n\n"); emit.next(m); }; diff --git a/apps/cli/cli-web/src/components/logs.tsx b/apps/cli/cli-web/src/components/logs.tsx index 3fff0d86..b235ef8f 100644 --- a/apps/cli/cli-web/src/components/logs.tsx +++ b/apps/cli/cli-web/src/components/logs.tsx @@ -7,7 +7,7 @@ export const Logs = () => { onData: (data) => { console.log("new message received"); setMessages((messages) => { - return [...messages, data.message]; + return [...messages, JSON.stringify(data, null, 2)]; }); }, }); @@ -15,7 +15,7 @@ export const Logs = () => { console.log("messages", messages); return ( -
+
{messages.map((m) => ( {m} ))} diff --git a/apps/cli/cli/src/server.ts b/apps/cli/cli/src/server.ts index d9f3be3b..0967fcf2 100644 --- a/apps/cli/cli/src/server.ts +++ b/apps/cli/cli/src/server.ts @@ -77,7 +77,6 @@ export const startSocketServer = () => { }); console.log(`[INFO] WebSocket Server listening on ws://localhost:${WS_PORT}`); process.on("SIGTERM", () => { - console.log("SIGTERM"); handler.broadcastReconnectNotification(); wss.close(); }); @@ -108,6 +107,8 @@ export const startServer = async () => { ); } - return; + process.on("SIGTERM", () => { + server.close(); + }); }); }; From 600f93a4d6ab7ae976a523bd35c4c98668c7a9d8 Mon Sep 17 00:00:00 2001 From: "Mark R. Florkowski" Date: Thu, 16 Feb 2023 12:02:05 -0800 Subject: [PATCH 13/27] replace a bunch of console.logs --- apps/cli/cli-core/src/trpc.ts | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/apps/cli/cli-core/src/trpc.ts b/apps/cli/cli-core/src/trpc.ts index 4ce350d5..54f7c896 100644 --- a/apps/cli/cli-core/src/trpc.ts +++ b/apps/cli/cli-core/src/trpc.ts @@ -106,8 +106,8 @@ export const cliApiRouter = t.router({ try { await openInExplorer(path.join(HOOK_PATH, input.path)); } catch (e) { - console.log( - "[ERROR] Failed to open folder (unless you're on Windows, then this just happens)", + logger.error( + "Failed to open folder (unless you're on Windows, then this just happens)", e ); } @@ -147,7 +147,7 @@ export const cliApiRouter = t.router({ if (fs.existsSync(path.join(HOOK_PATH, configName))) { hasCustomConfig = true; - console.log(`[INFO] Found ${configName}, reading it`); + logger.info(`Found ${configName}, reading it`); const configFileContents = await fsPromises.readFile( path.join(HOOK_PATH, configName) ); @@ -173,8 +173,8 @@ export const cliApiRouter = t.router({ const data = await fsPromises.readFile(path.join(HOOK_PATH, file)); try { - console.log( - `[INFO] Sending to ${config.url} ${ + logger.info( + `Sending to ${config.url} ${ hasCustomConfig ? `with custom config from ${configName}` : "" }\n` ); @@ -185,18 +185,16 @@ export const cliApiRouter = t.router({ body: config.method !== "GET" ? data.toString() : undefined, }).then((res) => res.json()); - console.log( - `[INFO] Got response: \n\n${JSON.stringify(fetchedResult, null, 2)}\n` + logger.info( + `Got response: \n\n${JSON.stringify(fetchedResult, null, 2)}\n` ); return fetchedResult; } catch (e) { - console.log("\u001b[31m[ERROR] FAILED TO SEND"); + logger.error("FAILED TO SEND"); if ((e as { code: string }).code === "ECONNREFUSED") { - console.log( - "\u001b[31m[ERROR] Connection refused. Is the server running?" - ); + logger.error("Connection refused. Is the server running?"); } else { - console.log("\u001b[31m[ERROR] Unknown error", e); + logger.error("Unknown error", e); } throw new Error("Connection refused. Is the server running?"); } @@ -212,11 +210,11 @@ export const cliApiRouter = t.router({ ) .mutation(async ({ input }) => { const { name, body, config } = input; - console.log(`[INFO] Creating ${name}.json`); + logger.info(`Creating ${name}.json`); await fsPromises.writeFile(path.join(HOOK_PATH, `${name}.json`), body); if (config?.url || config?.query || config?.headers) { - console.log(`[INFO] Config specified, creating ${name}.config.json`); + logger.info(`Config specified, creating ${name}.config.json`); return await updateConfig({ name, config }); } }), @@ -235,7 +233,7 @@ export const cliApiRouter = t.router({ if (!name) throw new Error("No name"); - console.log(`[INFO] updating ${name}.json`); + logger.info(`Updating ${name}.json`); const existingBody = await fsPromises.readFile( path.join(HOOK_PATH, `${name}.json`), @@ -263,7 +261,7 @@ export const cliApiRouter = t.router({ config?.headers || fs.existsSync(path.join(HOOK_PATH, `${name}.config.json`)) ) { - console.log(`[INFO] Config specified, updating ${name}.config.json`); + logger.info(`Config specified, updating ${name}.config.json`); return await updateConfig({ name, config }); } }), From 4d50fff8f87f2ea5a0833d8837611e66b57e993d Mon Sep 17 00:00:00 2001 From: "Mark R. Florkowski" Date: Thu, 16 Feb 2023 12:16:33 -0800 Subject: [PATCH 14/27] replace more logs --- apps/cli/cli-core/src/get-sample-hooks.ts | 14 +++++------ apps/cli/cli-core/src/open-folder.ts | 6 ++--- apps/cli/cli-core/src/templateSubstitution.ts | 8 +++---- apps/cli/cli/src/index.ts | 5 +--- apps/cli/cli/src/server.ts | 24 +++++++++---------- 5 files changed, 26 insertions(+), 31 deletions(-) diff --git a/apps/cli/cli-core/src/get-sample-hooks.ts b/apps/cli/cli-core/src/get-sample-hooks.ts index e997c19b..667325d7 100644 --- a/apps/cli/cli-core/src/get-sample-hooks.ts +++ b/apps/cli/cli-core/src/get-sample-hooks.ts @@ -2,14 +2,14 @@ import path from "path"; import fs from "fs"; import fsPromise from "fs/promises"; import fetch from "node-fetch"; + import { HOOK_PATH } from "./constants"; +import logger from "@captain/logger"; export async function getSampleHooks() { // Create the directory if it doesn't exist if (!fs.existsSync(HOOK_PATH)) { - console.log( - `\x1b[33m[WARNING] Could not find .thing directory, creating it now!\x1b[0m` - ); + logger.warn(`Could not find .thing directory, creating it now!`); fs.mkdirSync(HOOK_PATH, { recursive: true }); } @@ -20,10 +20,10 @@ export async function getSampleHooks() { download_url: string; }[]; - console.log(`[INFO] Downloading ${files.length} sample hooks.`); + logger.info(`Downloading ${files.length} sample hooks.`); const promiseMap = files.map(async (file) => { - console.log(`[INFO] Downloading ${file.name}`); + logger.info(`Downloading ${file.name}`); const fileContent = await fetch(file.download_url).then((res) => res.text() ); @@ -32,8 +32,8 @@ export async function getSampleHooks() { try { return await fsPromise.writeFile(newFilePath, fileContent); } catch (e) { - console.log(`[ERROR] Could not write file ${file.name}`); - console.log(e); + logger.error(`Could not write file ${file.name}`); + logger.error(`Error: ${e}`); throw e; } }); diff --git a/apps/cli/cli-core/src/open-folder.ts b/apps/cli/cli-core/src/open-folder.ts index 477b40f7..f69f9567 100644 --- a/apps/cli/cli-core/src/open-folder.ts +++ b/apps/cli/cli-core/src/open-folder.ts @@ -3,6 +3,8 @@ import { promisify } from "util"; import os from "os"; import fs from "fs"; +import logger from "@captain/logger"; + const promisifiedExecFile = promisify(childProcess.execFile); const getCommand = () => { @@ -23,9 +25,7 @@ const getCommand = () => { export async function openInExplorer(path: string) { // Create the directory if it doesn't exist if (!fs.existsSync(path)) { - console.log( - `\x1b[33m[WARNING] Could not find .thing directory, creating it now!\x1b[0m` - ); + logger.warn(`Could not find .thing directory, creating it now!`); fs.mkdirSync(path, { recursive: true }); } diff --git a/apps/cli/cli-core/src/templateSubstitution.ts b/apps/cli/cli-core/src/templateSubstitution.ts index 6ab37af2..d27c1352 100644 --- a/apps/cli/cli-core/src/templateSubstitution.ts +++ b/apps/cli/cli-core/src/templateSubstitution.ts @@ -1,3 +1,5 @@ +import logger from "@captain/logger"; + export const substituteTemplate = (input: { template: string; sanitize?: boolean; @@ -13,7 +15,7 @@ export const substituteTemplate = (input: { const variable = match[1]?.trim(); if (!variable) { - console.log(`\u001b[31m[ERROR] Invalid template configuration`); + logger.error(`Invalid template configuration`); throw new Error(`Invalid template configuration`); } const sanitizedString = `%%${variable}%%`; @@ -21,9 +23,7 @@ export const substituteTemplate = (input: { const fromEnv = process.env[variable]; if (!fromEnv) { - console.log( - `\u001b[31m[ERROR] Environment variable ${variable} not found` - ); + logger.error(`Environment variable ${variable} not found`); throw new Error(`Environment variable ${variable} not found`); } diff --git a/apps/cli/cli/src/index.ts b/apps/cli/cli/src/index.ts index 5ddb53d1..cb48f193 100644 --- a/apps/cli/cli/src/index.ts +++ b/apps/cli/cli/src/index.ts @@ -8,10 +8,7 @@ const main = async () => { renderTitle(); // link to docs - console.log( - `\x1b[36m%s\x1b[0m`, - `Questions? Check out the docs: ${DOCS_LINK}` - ); + console.log(`\x1b[36mQuestions? Check out the docs: ${DOCS_LINK}\x1b[0m`); startSocketServer(); diff --git a/apps/cli/cli/src/server.ts b/apps/cli/cli/src/server.ts index 0967fcf2..e2a18b76 100644 --- a/apps/cli/cli/src/server.ts +++ b/apps/cli/cli/src/server.ts @@ -8,6 +8,8 @@ import { cliApiRouter } from "@captain/cli-core"; import { fastifyStatic } from "@fastify/static"; import path from "path"; +import logger from "@captain/logger"; + const PORT = 2033; const WS_PORT = 2034; @@ -52,9 +54,9 @@ const openInBrowser = async () => { try { await open(`http://localhost:${PORT}`); } catch (_err) { - console.log("\x1b[31m[ERROR] Failed to open browser automatically\x1b[0m"); - console.log( - `[INFO] You can still manually open the web UI here: http://localhost:${PORT}` + logger.error("Failed to open browser automatically"); + logger.info( + `You can still manually open the web UI here: http://localhost:${PORT}` ); } }; @@ -69,10 +71,10 @@ export const startSocketServer = () => { const handler = applyWSSHandler({ wss, router: cliApiRouter }); wss.on("connection", (ws) => { if (process.env.NODE_ENV === "development") - console.log(`Websocket Connection ++ (${wss.clients.size})`); + logger.debug(`Websocket Connection ++ (${wss.clients.size})`); ws.once("close", () => { if (process.env.NODE_ENV === "development") - console.log(`Websocket Connection -- (${wss.clients.size})`); + logger.debug(`Websocket Connection -- (${wss.clients.size})`); }); }); console.log(`[INFO] WebSocket Server listening on ws://localhost:${WS_PORT}`); @@ -90,21 +92,17 @@ export const startServer = async () => { process.exit(1); } if (process.env.NODE_ENV === "development") { - console.log( - `\x1b[33m[WARNING] Running in development mode, you can access the web UI at http://localhost:5173\x1b[0m` + logger.warn( + `Running in development mode, you can access the web UI at http://localhost:5173` ); } // eslint-disable-next-line turbo/no-undeclared-env-vars else if (!process.env.CI && !process.env.CODESPACES) { // Dont try to open the browser in CI, or on Codespaces, it will crash - console.log( - `[INFO] Opening webhookthing at address: http://localhost:${PORT}` - ); + logger.info(`Opening webhookthing at address: http://localhost:${PORT}`); void openInBrowser(); } else { - console.log( - `[INFO] Running webhookthing at address: http://localhost:${PORT}` - ); + logger.info(`Running webhookthing at address: http://localhost:${PORT}`); } process.on("SIGTERM", () => { From 327513a5f26a83d295c56e33308cc74e56dc9ca3 Mon Sep 17 00:00:00 2001 From: "Mark R. Florkowski" Date: Thu, 16 Feb 2023 12:38:18 -0800 Subject: [PATCH 15/27] more cleanup --- apps/cli/cli-web/package.json | 1 + apps/cli/cli-web/src/components/logs.tsx | 34 +++++++++++++++++------- packages/logger/src/index.ts | 12 ++++++--- pnpm-lock.yaml | 2 ++ 4 files changed, 35 insertions(+), 14 deletions(-) diff --git a/apps/cli/cli-web/package.json b/apps/cli/cli-web/package.json index 8de949fd..cae2ba5f 100644 --- a/apps/cli/cli-web/package.json +++ b/apps/cli/cli-web/package.json @@ -13,6 +13,7 @@ "format:check": "prettier --check --plugin-search-dir=. src/**/*.{cjs,mjs,ts,tsx,md,json} --ignore-path ../.gitignore" }, "dependencies": { + "@captain/logger": "workspace:*", "@headlessui/react": "^1.7.8", "@heroicons/react": "^2.0.12", "@hookform/resolvers": "^2.9.10", diff --git a/apps/cli/cli-web/src/components/logs.tsx b/apps/cli/cli-web/src/components/logs.tsx index b235ef8f..e53625ce 100644 --- a/apps/cli/cli-web/src/components/logs.tsx +++ b/apps/cli/cli-web/src/components/logs.tsx @@ -1,24 +1,38 @@ -import { useState } from "react"; +import { ReactNode, useState } from "react"; import { cliApi } from "../utils/api"; +import type { LogLevels } from "@captain/logger"; + +const colorMap = { + trace: "text-gray-600", // gray + debug: `text-cyan-600`, // cyan + info: `text-white`, // white + warn: `text-yellow-600`, // yellow + error: `text-red-600`, // red +} as const; + +const webFormat = (input: { level: LogLevels; message: string }) => { + const { level, message } = input; + return ( + + [{level.toUpperCase()}] {message} + + ); +}; + export const Logs = () => { - const [messages, setMessages] = useState([]); + const [messages, setMessages] = useState([]); cliApi.onLog.useSubscription(undefined, { onData: (data) => { - console.log("new message received"); setMessages((messages) => { - return [...messages, JSON.stringify(data, null, 2)]; + return [...messages, webFormat(data)]; }); }, }); - console.log("messages", messages); - return ( -
- {messages.map((m) => ( - {m} - ))} +
+ {...messages}
); }; diff --git a/packages/logger/src/index.ts b/packages/logger/src/index.ts index 766760cc..d94c425b 100644 --- a/packages/logger/src/index.ts +++ b/packages/logger/src/index.ts @@ -66,10 +66,7 @@ class logger implements Logger { } private log(level: LogLevels, message: string, optionalParams: any[]) { - console[level]( - `${prefixColors[level]}[${level.toUpperCase()}] ${message}${colorReset}`, - ...optionalParams - ); + console[level](consoleFormat(level, message), ...optionalParams); this.subscriptions.forEach(({ fn, level: subLevel }) => { if (getLogLevels(subLevel).includes(level)) fn({ message, level }); @@ -82,6 +79,13 @@ const getLogLevels = (level: LogLevels): LogLevels[] => { return levels.slice(levels.indexOf(level)); }; +// formatting +const consoleFormat = (level: LogLevels, message: string) => { + return `${ + prefixColors[level] + }[${level.toUpperCase()}] ${message}${colorReset}`; +}; + const loggerInstance = new logger(); export default loggerInstance; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e38ccb0d..b930f887 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -100,6 +100,7 @@ importers: apps/cli/cli-web: specifiers: '@captain/cli-core': '*' + '@captain/logger': workspace:* '@captain/tailwind-config': '*' '@captain/tsconfig': workspace:* '@headlessui/react': ^1.7.8 @@ -130,6 +131,7 @@ importers: vite: ^4.0.0 zod: ^3.19.1 dependencies: + '@captain/logger': link:../../../packages/logger '@headlessui/react': 1.7.8_biqbaboplfbrettd7655fr4n2y '@heroicons/react': 2.0.14_react@18.2.0 '@hookform/resolvers': 2.9.10_react-hook-form@7.43.0 From 1ff41932a33665afc150fbf69a8867596148ae3d Mon Sep 17 00:00:00 2001 From: "Mark R. Florkowski" Date: Thu, 16 Feb 2023 12:41:06 -0800 Subject: [PATCH 16/27] a few more console logs swapped --- apps/cli/cli-web/src/utils/api-wrapper.tsx | 3 +-- apps/cli/cli/src/server.ts | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/cli/cli-web/src/utils/api-wrapper.tsx b/apps/cli/cli-web/src/utils/api-wrapper.tsx index 6b08be76..fa7e2551 100644 --- a/apps/cli/cli-web/src/utils/api-wrapper.tsx +++ b/apps/cli/cli-web/src/utils/api-wrapper.tsx @@ -20,9 +20,8 @@ export const ApiTRPCProvider = (props: PropsWithChildren) => { transformer: superjson, links: [ splitLink({ + // subscriptions are handled by WebSocket, everything else is handled by HTTP condition(op) { - console.log("operation?", op); - // check for context property `skipBatch` return op.type === "subscription"; }, true: wsLink({ diff --git a/apps/cli/cli/src/server.ts b/apps/cli/cli/src/server.ts index e2a18b76..6e58b89a 100644 --- a/apps/cli/cli/src/server.ts +++ b/apps/cli/cli/src/server.ts @@ -77,7 +77,8 @@ export const startSocketServer = () => { logger.debug(`Websocket Connection -- (${wss.clients.size})`); }); }); - console.log(`[INFO] WebSocket Server listening on ws://localhost:${WS_PORT}`); + if (process.env.NODE_ENV === "development") + logger.debug(`WebSocket Server listening on ws://localhost:${WS_PORT}`); process.on("SIGTERM", () => { handler.broadcastReconnectNotification(); wss.close(); From 3b7fabd306435c37a3f5eb80377e2a84d5ac9794 Mon Sep 17 00:00:00 2001 From: "Mark R. Florkowski" Date: Thu, 16 Feb 2023 13:01:37 -0800 Subject: [PATCH 17/27] no-console lint rule --- apps/cli/cli-core/src/get-sample-hooks.ts | 1 - apps/cli/cli-web/src/components/logs.tsx | 3 ++- apps/cli/cli/src/index.ts | 3 ++- apps/cli/cli/src/server.ts | 4 ++-- apps/cli/cli/src/utils/renderTitle.ts | 1 + apps/marketing/src/env/client.mjs | 2 ++ apps/marketing/src/env/server.mjs | 2 ++ apps/marketing/src/pages/api/trpc/[trpc].ts | 2 ++ apps/marketing/src/server/api/routers/example.ts | 1 + packages/eslint-config-custom/index.js | 1 + packages/logger/src/index.ts | 2 ++ 11 files changed, 17 insertions(+), 5 deletions(-) diff --git a/apps/cli/cli-core/src/get-sample-hooks.ts b/apps/cli/cli-core/src/get-sample-hooks.ts index 667325d7..7881fdc4 100644 --- a/apps/cli/cli-core/src/get-sample-hooks.ts +++ b/apps/cli/cli-core/src/get-sample-hooks.ts @@ -33,7 +33,6 @@ export async function getSampleHooks() { return await fsPromise.writeFile(newFilePath, fileContent); } catch (e) { logger.error(`Could not write file ${file.name}`); - logger.error(`Error: ${e}`); throw e; } }); diff --git a/apps/cli/cli-web/src/components/logs.tsx b/apps/cli/cli-web/src/components/logs.tsx index e53625ce..c3c39056 100644 --- a/apps/cli/cli-web/src/components/logs.tsx +++ b/apps/cli/cli-web/src/components/logs.tsx @@ -15,7 +15,8 @@ const webFormat = (input: { level: LogLevels; message: string }) => { const { level, message } = input; return ( - [{level.toUpperCase()}] {message} + {`[${level.toUpperCase()}]`}{" "} + {message} ); }; diff --git a/apps/cli/cli/src/index.ts b/apps/cli/cli/src/index.ts index cb48f193..632b9550 100644 --- a/apps/cli/cli/src/index.ts +++ b/apps/cli/cli/src/index.ts @@ -7,7 +7,7 @@ const DOCS_LINK = "https://docs.webhookthing.com"; const main = async () => { renderTitle(); - // link to docs + // eslint-disable-next-line no-console console.log(`\x1b[36mQuestions? Check out the docs: ${DOCS_LINK}\x1b[0m`); startSocketServer(); @@ -16,6 +16,7 @@ const main = async () => { }; main().catch((err) => { + // eslint-disable-next-line no-console console.error(err); process.exit(1); }); diff --git a/apps/cli/cli/src/server.ts b/apps/cli/cli/src/server.ts index 6e58b89a..07301cb7 100644 --- a/apps/cli/cli/src/server.ts +++ b/apps/cli/cli/src/server.ts @@ -89,7 +89,7 @@ export const startServer = async () => { const server = await createServer(); server.listen({ port: PORT }, (err) => { if (err) { - console.error(err); + logger.error(err.message, err.name, err.stack, err.cause); process.exit(1); } if (process.env.NODE_ENV === "development") { @@ -107,7 +107,7 @@ export const startServer = async () => { } process.on("SIGTERM", () => { - server.close(); + void server.close(); }); }); }; diff --git a/apps/cli/cli/src/utils/renderTitle.ts b/apps/cli/cli/src/utils/renderTitle.ts index cc41b1a2..737c6f36 100644 --- a/apps/cli/cli/src/utils/renderTitle.ts +++ b/apps/cli/cli/src/utils/renderTitle.ts @@ -14,5 +14,6 @@ const poimandresTheme = { export const renderTitle = () => { const captGradient = gradient(Object.values(poimandresTheme)); + // eslint-disable-next-line no-console console.log(captGradient.multiline(TITLE_TEXT)); }; diff --git a/apps/marketing/src/env/client.mjs b/apps/marketing/src/env/client.mjs index ab5f17f9..928bf6e3 100644 --- a/apps/marketing/src/env/client.mjs +++ b/apps/marketing/src/env/client.mjs @@ -1,4 +1,6 @@ // @ts-check +/* eslint-disable no-console */ + import { clientEnv, clientSchema } from "./schema.mjs"; const _clientEnv = clientSchema.safeParse(clientEnv); diff --git a/apps/marketing/src/env/server.mjs b/apps/marketing/src/env/server.mjs index d590c942..2289ae29 100644 --- a/apps/marketing/src/env/server.mjs +++ b/apps/marketing/src/env/server.mjs @@ -1,4 +1,6 @@ // @ts-check +/* eslint-disable no-console */ + /** * This file is included in `/next.config.mjs` which ensures the app isn't built with invalid env vars. * It has to be a `.mjs`-file to be imported there. diff --git a/apps/marketing/src/pages/api/trpc/[trpc].ts b/apps/marketing/src/pages/api/trpc/[trpc].ts index b746eded..dfe2b072 100644 --- a/apps/marketing/src/pages/api/trpc/[trpc].ts +++ b/apps/marketing/src/pages/api/trpc/[trpc].ts @@ -1,3 +1,5 @@ +/* eslint-disable no-console */ + import { createNextApiHandler } from "@trpc/server/adapters/next"; import { env } from "../../../env/server.mjs"; diff --git a/apps/marketing/src/server/api/routers/example.ts b/apps/marketing/src/server/api/routers/example.ts index 003d278e..8294669f 100644 --- a/apps/marketing/src/server/api/routers/example.ts +++ b/apps/marketing/src/server/api/routers/example.ts @@ -1,3 +1,4 @@ +/* eslint-disable no-console */ import { z } from "zod"; import { createTRPCRouter, publicProcedure } from "../trpc"; diff --git a/packages/eslint-config-custom/index.js b/packages/eslint-config-custom/index.js index 523f7307..7a5492b5 100644 --- a/packages/eslint-config-custom/index.js +++ b/packages/eslint-config-custom/index.js @@ -25,6 +25,7 @@ module.exports = { }, }, ], + "no-console": "warn", // Allows for _ prefixed variables to be unused // Ripped from https://stackoverflow.com/questions/64052318/how-to-disable-warn-about-some-unused-params-but-keep-typescript-eslint-no-un diff --git a/packages/logger/src/index.ts b/packages/logger/src/index.ts index d94c425b..01a8551d 100644 --- a/packages/logger/src/index.ts +++ b/packages/logger/src/index.ts @@ -1,5 +1,7 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-unsafe-argument */ +/* eslint-disable no-console */ + interface Logger { trace(message: string, ...optionalParams: any[]): void; debug(message: string, ...optionalParams: any[]): void; From 9d7f146bb4ec465fbc3d463a41c73bc817f17f0a Mon Sep 17 00:00:00 2001 From: "Mark R. Florkowski" Date: Thu, 16 Feb 2023 13:09:53 -0800 Subject: [PATCH 18/27] disable no-console on docs and marketing site --- apps/docs/.eslintrc.js | 6 ++++++ apps/marketing/.eslintrc.js | 6 ++++++ apps/marketing/src/env/client.mjs | 1 - apps/marketing/src/env/server.mjs | 1 - apps/marketing/src/pages/api/trpc/[trpc].ts | 2 -- apps/marketing/src/server/api/routers/example.ts | 1 - packages/logger/.eslintrc.js | 6 ++++++ packages/logger/src/index.ts | 1 - 8 files changed, 18 insertions(+), 6 deletions(-) create mode 100644 apps/docs/.eslintrc.js create mode 100644 apps/marketing/.eslintrc.js create mode 100644 packages/logger/.eslintrc.js diff --git a/apps/docs/.eslintrc.js b/apps/docs/.eslintrc.js new file mode 100644 index 00000000..6db54e02 --- /dev/null +++ b/apps/docs/.eslintrc.js @@ -0,0 +1,6 @@ +module.exports = { + extends: ["custom"], + rules: { + "no-console": "off", + }, +}; diff --git a/apps/marketing/.eslintrc.js b/apps/marketing/.eslintrc.js new file mode 100644 index 00000000..6db54e02 --- /dev/null +++ b/apps/marketing/.eslintrc.js @@ -0,0 +1,6 @@ +module.exports = { + extends: ["custom"], + rules: { + "no-console": "off", + }, +}; diff --git a/apps/marketing/src/env/client.mjs b/apps/marketing/src/env/client.mjs index 928bf6e3..dc09e6d1 100644 --- a/apps/marketing/src/env/client.mjs +++ b/apps/marketing/src/env/client.mjs @@ -1,5 +1,4 @@ // @ts-check -/* eslint-disable no-console */ import { clientEnv, clientSchema } from "./schema.mjs"; diff --git a/apps/marketing/src/env/server.mjs b/apps/marketing/src/env/server.mjs index 2289ae29..9e18c9c0 100644 --- a/apps/marketing/src/env/server.mjs +++ b/apps/marketing/src/env/server.mjs @@ -1,5 +1,4 @@ // @ts-check -/* eslint-disable no-console */ /** * This file is included in `/next.config.mjs` which ensures the app isn't built with invalid env vars. diff --git a/apps/marketing/src/pages/api/trpc/[trpc].ts b/apps/marketing/src/pages/api/trpc/[trpc].ts index dfe2b072..b746eded 100644 --- a/apps/marketing/src/pages/api/trpc/[trpc].ts +++ b/apps/marketing/src/pages/api/trpc/[trpc].ts @@ -1,5 +1,3 @@ -/* eslint-disable no-console */ - import { createNextApiHandler } from "@trpc/server/adapters/next"; import { env } from "../../../env/server.mjs"; diff --git a/apps/marketing/src/server/api/routers/example.ts b/apps/marketing/src/server/api/routers/example.ts index 8294669f..003d278e 100644 --- a/apps/marketing/src/server/api/routers/example.ts +++ b/apps/marketing/src/server/api/routers/example.ts @@ -1,4 +1,3 @@ -/* eslint-disable no-console */ import { z } from "zod"; import { createTRPCRouter, publicProcedure } from "../trpc"; diff --git a/packages/logger/.eslintrc.js b/packages/logger/.eslintrc.js new file mode 100644 index 00000000..6db54e02 --- /dev/null +++ b/packages/logger/.eslintrc.js @@ -0,0 +1,6 @@ +module.exports = { + extends: ["custom"], + rules: { + "no-console": "off", + }, +}; diff --git a/packages/logger/src/index.ts b/packages/logger/src/index.ts index 01a8551d..03fa06fc 100644 --- a/packages/logger/src/index.ts +++ b/packages/logger/src/index.ts @@ -1,6 +1,5 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-unsafe-argument */ -/* eslint-disable no-console */ interface Logger { trace(message: string, ...optionalParams: any[]): void; From 7808c9e951318a30401fb64947b0ffa8d1ec194c Mon Sep 17 00:00:00 2001 From: "Mark R. Florkowski" Date: Thu, 16 Feb 2023 13:11:48 -0800 Subject: [PATCH 19/27] add missing dep --- apps/cli/cli/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/cli/cli/package.json b/apps/cli/cli/package.json index db058654..40ca3311 100644 --- a/apps/cli/cli/package.json +++ b/apps/cli/cli/package.json @@ -26,6 +26,7 @@ }, "dependencies": { "@captain/cli-core": "*", + "@captain/logger": "workspace:*", "@fastify/cors": "^8.2.0", "@fastify/http-proxy": "^8.4.0", "@fastify/static": "^6.6.0", From ce5e4f96a67ba34ee2b1d81e4007a440811340e4 Mon Sep 17 00:00:00 2001 From: "Mark R. Florkowski" Date: Thu, 16 Feb 2023 13:15:42 -0800 Subject: [PATCH 20/27] pnpm i --- pnpm-lock.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b930f887..c0fc2d04 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -22,6 +22,7 @@ importers: specifiers: '@captain/cli-core': '*' '@captain/cli-web': '*' + '@captain/logger': workspace:* '@captain/tsconfig': workspace:* '@fastify/cors': ^8.2.0 '@fastify/http-proxy': ^8.4.0 @@ -46,6 +47,7 @@ importers: ws: ^8.12.1 dependencies: '@captain/cli-core': link:../cli-core + '@captain/logger': link:../../../packages/logger '@fastify/cors': 8.2.0 '@fastify/http-proxy': 8.4.0 '@fastify/static': 6.7.0 From e40d319ace65d2e39ba6ff29246ca30c97311c22 Mon Sep 17 00:00:00 2001 From: Theo Browne Date: Thu, 16 Feb 2023 14:53:51 -0800 Subject: [PATCH 21/27] fix vscode side --- .vscode/settings.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 764a1867..b91082dc 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -11,6 +11,7 @@ "apps/cli/cli-core", "apps/cli/cli-web", "apps/docs", - "apps/marketing" + "apps/marketing", + "packages/logger" ] } From ddc3050b78c07a838f28b139659571b208df21fe Mon Sep 17 00:00:00 2001 From: Theo Browne Date: Thu, 16 Feb 2023 15:57:28 -0800 Subject: [PATCH 22/27] Fix logger in cli --- apps/cli/cli/tsup.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/cli/cli/tsup.config.ts b/apps/cli/cli/tsup.config.ts index ddcafb7d..7ee5bfdf 100644 --- a/apps/cli/cli/tsup.config.ts +++ b/apps/cli/cli/tsup.config.ts @@ -18,5 +18,5 @@ export default defineConfig({ shims: true, - noExternal: ["@captain/cli-core"], + noExternal: ["@captain/cli-core", "@captain/logger"], }); From 4069899650fff2fe4ec1c2f6c8890ac694ee72b1 Mon Sep 17 00:00:00 2001 From: "Mark R. Florkowski" Date: Thu, 16 Feb 2023 16:42:18 -0800 Subject: [PATCH 23/27] allow passing Error objects to logger --- apps/cli/cli/src/server.ts | 2 +- packages/logger/src/index.ts | 70 ++++++++++++++++++++++++++++++------ 2 files changed, 61 insertions(+), 11 deletions(-) diff --git a/apps/cli/cli/src/server.ts b/apps/cli/cli/src/server.ts index 07301cb7..3883e698 100644 --- a/apps/cli/cli/src/server.ts +++ b/apps/cli/cli/src/server.ts @@ -89,7 +89,7 @@ export const startServer = async () => { const server = await createServer(); server.listen({ port: PORT }, (err) => { if (err) { - logger.error(err.message, err.name, err.stack, err.cause); + logger.error(err); process.exit(1); } if (process.env.NODE_ENV === "development") { diff --git a/packages/logger/src/index.ts b/packages/logger/src/index.ts index 03fa06fc..5228550f 100644 --- a/packages/logger/src/index.ts +++ b/packages/logger/src/index.ts @@ -32,24 +32,74 @@ class logger implements Logger { this.subscriptions = []; } - trace(message: string, ...optionalParams: any[]) { - this.log("trace", message, optionalParams); + trace(message: string | Error | unknown, ...optionalParams: any[]) { + if (message instanceof Error) { + this.log("trace", message.message, [ + optionalParams, + message.stack, + message.cause, + ]); + } else if (typeof message === "string") { + this.log("trace", message, optionalParams); + } else { + this.log("trace", JSON.stringify(message), optionalParams); + } } - debug(message: string, ...optionalParams: any[]) { - this.log("debug", message, optionalParams); + debug(message: string | Error | unknown, ...optionalParams: any[]) { + if (message instanceof Error) { + this.log("debug", message.message, [ + optionalParams, + message.stack, + message.cause, + ]); + } else if (typeof message === "string") { + this.log("debug", message, optionalParams); + } else { + this.log("debug", JSON.stringify(message), optionalParams); + } } - info(message: string, ...optionalParams: any[]) { - this.log("info", message, optionalParams); + info(message: string | Error | unknown, ...optionalParams: any[]) { + if (message instanceof Error) { + this.log("info", message.message, [ + optionalParams, + message.stack, + message.cause, + ]); + } else if (typeof message === "string") { + this.log("info", message, optionalParams); + } else { + this.log("info", JSON.stringify(message), optionalParams); + } } - warn(message: string, ...optionalParams: any[]) { - this.log("warn", message, optionalParams); + warn(message: string | Error | unknown, ...optionalParams: any[]) { + if (message instanceof Error) { + this.log("warn", message.message, [ + optionalParams, + message.stack, + message.cause, + ]); + } else if (typeof message === "string") { + this.log("warn", message, optionalParams); + } else { + this.log("warn", JSON.stringify(message), optionalParams); + } } - error(message: string, ...optionalParams: any[]) { - this.log("error", message, optionalParams); + error(message: string | Error | unknown, ...optionalParams: any[]) { + if (message instanceof Error) { + this.log("error", message.message, [ + optionalParams, + message.stack, + message.cause, + ]); + } else if (typeof message === "string") { + this.log("error", message, optionalParams); + } else { + this.log("error", JSON.stringify(message), optionalParams); + } } subscribe( From 38eb801856da3a0d24e07c1c17bc37131680fb84 Mon Sep 17 00:00:00 2001 From: "Mark R. Florkowski" Date: Thu, 16 Feb 2023 16:42:45 -0800 Subject: [PATCH 24/27] missing file --- apps/cli/cli-core/src/get-sample-hooks.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/cli/cli-core/src/get-sample-hooks.ts b/apps/cli/cli-core/src/get-sample-hooks.ts index 7881fdc4..77edae9c 100644 --- a/apps/cli/cli-core/src/get-sample-hooks.ts +++ b/apps/cli/cli-core/src/get-sample-hooks.ts @@ -33,6 +33,7 @@ export async function getSampleHooks() { return await fsPromise.writeFile(newFilePath, fileContent); } catch (e) { logger.error(`Could not write file ${file.name}`); + logger.error(e); throw e; } }); From aa5ab621162c41c5ba6fdc6df4a33bba88300c4c Mon Sep 17 00:00:00 2001 From: "Mark R. Florkowski" Date: Sun, 19 Feb 2023 22:28:38 -0800 Subject: [PATCH 25/27] combine dev checks --- apps/cli/cli/src/server.ts | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/apps/cli/cli/src/server.ts b/apps/cli/cli/src/server.ts index 3883e698..0b3e0fdb 100644 --- a/apps/cli/cli/src/server.ts +++ b/apps/cli/cli/src/server.ts @@ -69,16 +69,18 @@ export const startSocketServer = () => { port: WS_PORT, }); const handler = applyWSSHandler({ wss, router: cliApiRouter }); - wss.on("connection", (ws) => { - if (process.env.NODE_ENV === "development") + + // Debug logging for dev + if (process.env.NODE_ENV === "development") { + logger.debug(`WebSocket Server listening on ws://localhost:${WS_PORT}`); + wss.on("connection", (ws) => { logger.debug(`Websocket Connection ++ (${wss.clients.size})`); - ws.once("close", () => { - if (process.env.NODE_ENV === "development") + ws.once("close", () => { logger.debug(`Websocket Connection -- (${wss.clients.size})`); + }); }); - }); - if (process.env.NODE_ENV === "development") - logger.debug(`WebSocket Server listening on ws://localhost:${WS_PORT}`); + } + process.on("SIGTERM", () => { handler.broadcastReconnectNotification(); wss.close(); From 1e4af442c77e8f714dddbfabe7c389b6413ba12f Mon Sep 17 00:00:00 2001 From: "Mark R. Florkowski" Date: Sun, 19 Feb 2023 22:31:28 -0800 Subject: [PATCH 26/27] disable multiple eslint rules in one line --- packages/logger/src/index.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/logger/src/index.ts b/packages/logger/src/index.ts index 5228550f..7687f4c7 100644 --- a/packages/logger/src/index.ts +++ b/packages/logger/src/index.ts @@ -1,5 +1,4 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -/* eslint-disable @typescript-eslint/no-unsafe-argument */ +/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument */ interface Logger { trace(message: string, ...optionalParams: any[]): void; From b5c8614b7eb5a157144b0d56a88e084a535f6050 Mon Sep 17 00:00:00 2001 From: "Mark R. Florkowski" Date: Sun, 19 Feb 2023 22:34:25 -0800 Subject: [PATCH 27/27] don't store ReactNodes in state --- apps/cli/cli-web/src/components/logs.tsx | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/apps/cli/cli-web/src/components/logs.tsx b/apps/cli/cli-web/src/components/logs.tsx index c3c39056..fa35c0c4 100644 --- a/apps/cli/cli-web/src/components/logs.tsx +++ b/apps/cli/cli-web/src/components/logs.tsx @@ -22,18 +22,26 @@ const webFormat = (input: { level: LogLevels; message: string }) => { }; export const Logs = () => { - const [messages, setMessages] = useState([]); + const [messages, setMessages] = useState< + { level: LogLevels; message: string }[] + >([]); cliApi.onLog.useSubscription(undefined, { onData: (data) => { setMessages((messages) => { - return [...messages, webFormat(data)]; + return [...messages, data]; }); }, }); return (
- {...messages} + {messages.map((message, index) => { + return ( +
+ {webFormat(message)} +
+ ); + })}
); };