Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Posting capabilities #35

Open
wants to merge 12 commits into
base: development
Choose a base branch
from
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"devDependencies": {
"@commitlint/cli": "^18.4.3",
"@commitlint/config-conventional": "^18.4.3",
"@supabase/supabase-js": "^2.45.3",
"@types/jest": "^29.5.12",
"@types/node": "^20.10.4",
"@typescript-eslint/eslint-plugin": "^7.14.1",
Expand Down Expand Up @@ -67,6 +68,5 @@
"extends": [
"@commitlint/config-conventional"
]
},
"packageManager": "yarn@1.22.22"
}
}
82 changes: 72 additions & 10 deletions src/logs.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,50 @@
import { SupabaseClient } from "@supabase/supabase-js";
import { LOG_LEVEL } from "./constants";
import { PrettyLogs } from "./pretty-logs";
import { LogParams, LogReturn, Metadata, LogLevel } from "./types/log-types";

type SupabaseConfig = {
supabaseClient: SupabaseClient;
levelsToLog: LogLevel[];
};

export class Logs {
private _maxLevel = -1;
static console: PrettyLogs;
private _supabase: SupabaseClient | null = null;
private _pluginName: string;
private _levelsToLog: LogLevel[] = [];

constructor(level: LogLevel, pluginName: string, postingConfig?: SupabaseConfig) {
this._log = this._log.bind(this);
this._logToSupabase = this._logToSupabase.bind(this);
this._diffColorCommentMessage = this._diffColorCommentMessage.bind(this);
this._getNumericLevel = this._getNumericLevel.bind(this);
this.ok = this.ok.bind(this);
this.info = this.info.bind(this);
this.error = this.error.bind(this);
this.debug = this.debug.bind(this);
this.fatal = this.fatal.bind(this);
this.verbose = this.verbose.bind(this);
this._addDiagnosticInformation = this._addDiagnosticInformation.bind(this);

this._maxLevel = this._getNumericLevel(level);
Logs.console = new PrettyLogs();
this._pluginName = pluginName;

if (postingConfig) {
this._levelsToLog = postingConfig.levelsToLog;
this._supabase = postingConfig.supabaseClient;
}
}

private _log({ level, consoleLog, logMessage, metadata, type }: LogParams): LogReturn {
// filter out more verbose logs according to maxLevel set in config
if (this._getNumericLevel(level) <= this._maxLevel) {
consoleLog(logMessage, metadata);
}

return new LogReturn(
const log = new LogReturn(
{
raw: logMessage,
diff: this._diffColorCommentMessage(type, logMessage),
Expand All @@ -21,6 +53,12 @@ export class Logs {
},
metadata
);

if (this._supabase && this._levelsToLog.includes(level)) {
this._logToSupabase(log).catch((error) => this.error(error.message, { error }));
}

return log;
}

private _addDiagnosticInformation(metadata?: Metadata) {
Expand Down Expand Up @@ -92,14 +130,14 @@ export class Logs {

public fatal(log: string, metadata?: Metadata): LogReturn {
if (!metadata) {
metadata = Logs.convertErrorsIntoObjects(new Error(log)) as Metadata;
metadata = Logs.convertErrorsIntoObjects(new Error(log));
const stack = metadata.stack as string[];
stack.splice(1, 1);
metadata.stack = stack;
}

if (metadata instanceof Error) {
metadata = Logs.convertErrorsIntoObjects(metadata) as Metadata;
metadata = Logs.convertErrorsIntoObjects(metadata);
const stack = metadata.stack as string[];
stack.splice(1, 1);
metadata.stack = stack;
Expand All @@ -126,12 +164,13 @@ export class Logs {
});
}

constructor(logLevel: LogLevel) {
this._maxLevel = this._getNumericLevel(logLevel);
Logs.console = new PrettyLogs();
}

private _diffColorCommentMessage(type: string, message: string) {
if (!message) {
return "";
}
if (typeof message !== "string") {
message = JSON.stringify(message, null, 2);
}
const diffPrefix = {
fatal: "-", // - text in red
ok: "+", // + text in green
Expand Down Expand Up @@ -183,7 +222,8 @@ export class Logs {
return -1;
}
}
static convertErrorsIntoObjects(obj: unknown): Metadata | unknown {

static convertErrorsIntoObjects(obj: unknown): Metadata {
// this is a utility function to render native errors in the console, the database, and on GitHub.
if (obj instanceof Error) {
return {
Expand All @@ -197,6 +237,28 @@ export class Logs {
obj[key] = this.convertErrorsIntoObjects(obj[key]);
});
}
return obj;
return obj as Metadata;
}

private async _logToSupabase(log: LogReturn) {
if (!this._supabase) {
return;
}
try {
const { data, error } = await this._supabase.from("logs").insert([
{
log: log.logMessage.raw,
level: log.logMessage.level,
metadata: { ...log.metadata, caller: this._pluginName },
},
]);
if (error) {
throw error;
}
return data;
} catch (err) {
console.error("Error logging to Supabase:", err);
throw err;
}
}
}
3 changes: 2 additions & 1 deletion src/types/log-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@ interface MetadataInterface {

export type Metadata = Partial<MetadataInterface>;

export class LogReturn {
export class LogReturn extends Error {
logMessage: LogMessage;
metadata?: Metadata;

constructor(logMessage: LogMessage, metadata?: Metadata) {
super(logMessage.raw);
this.logMessage = logMessage;
this.metadata = metadata;
}
Expand Down
26 changes: 25 additions & 1 deletion tests/logs.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,25 @@
import { SupabaseClient } from "@supabase/supabase-js";
import { LOG_LEVEL } from "../src/constants";
import { Logs } from "../src/logs";
import { LogReturn } from "../src/types/log-types";

jest.mock("@supabase/supabase-js", () => {
return {
SupabaseClient: jest.fn().mockImplementation(() => {
return {
from: jest.fn().mockImplementation(() => {
throw new Error("This is the error you are looking for.");
}),
};
}),
};
});

describe("Logs", () => {
let logs: Logs;

beforeEach(() => {
logs = new Logs(LOG_LEVEL.DEBUG);
logs = new Logs(LOG_LEVEL.DEBUG, "test");
});

it("should log an 'ok' message", () => {
Expand Down Expand Up @@ -47,4 +60,15 @@ describe("Logs", () => {
expect(msg).toHaveProperty("diff");
expect(metadata).toHaveProperty("caller");
});

it("should log an error when _logToSupabase throws an error", async () => {
const supabaseClient = new SupabaseClient("test", "test");
const logger = new Logs(LOG_LEVEL.DEBUG, "test", { levelsToLog: ["fatal"], supabaseClient });
const spy = jest.spyOn(console, "error");
logger.fatal("This is not the error you are looking for");
await new Promise((resolve) => setTimeout(resolve, 100));

expect(spy).toHaveBeenCalled();
expect(spy).toHaveBeenLastCalledWith("Error logging to Supabase:", new Error("This is the error you are looking for."));
});
});
92 changes: 92 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1323,6 +1323,63 @@
ignore "^5.1.8"
p-map "^4.0.0"

"@supabase/auth-js@2.65.0":
version "2.65.0"
resolved "https://registry.yarnpkg.com/@supabase/auth-js/-/auth-js-2.65.0.tgz#e345c492f8cbc31cd6289968eae0e349ff0f39e9"
integrity sha512-+wboHfZufAE2Y612OsKeVP4rVOeGZzzMLD/Ac3HrTQkkY4qXNjI6Af9gtmxwccE5nFvTiF114FEbIQ1hRq5uUw==
dependencies:
"@supabase/node-fetch" "^2.6.14"

"@supabase/functions-js@2.4.1":
version "2.4.1"
resolved "https://registry.yarnpkg.com/@supabase/functions-js/-/functions-js-2.4.1.tgz#373e75f8d3453bacd71fb64f88d7a341d7b53ad7"
integrity sha512-8sZ2ibwHlf+WkHDUZJUXqqmPvWQ3UHN0W30behOJngVh/qHHekhJLCFbh0AjkE9/FqqXtf9eoVvmYgfCLk5tNA==
dependencies:
"@supabase/node-fetch" "^2.6.14"

"@supabase/node-fetch@2.6.15", "@supabase/node-fetch@^2.6.14":
version "2.6.15"
resolved "https://registry.yarnpkg.com/@supabase/node-fetch/-/node-fetch-2.6.15.tgz#731271430e276983191930816303c44159e7226c"
integrity sha512-1ibVeYUacxWYi9i0cf5efil6adJ9WRyZBLivgjs+AUpewx1F3xPi7gLgaASI2SmIQxPoCEjAsLAzKPgMJVgOUQ==
dependencies:
whatwg-url "^5.0.0"

"@supabase/postgrest-js@1.15.8":
version "1.15.8"
resolved "https://registry.yarnpkg.com/@supabase/postgrest-js/-/postgrest-js-1.15.8.tgz#827aaa408cdbc89e67d0a758e7a545ac86e34312"
integrity sha512-YunjXpoQjQ0a0/7vGAvGZA2dlMABXFdVI/8TuVKtlePxyT71sl6ERl6ay1fmIeZcqxiuFQuZw/LXUuStUG9bbg==
dependencies:
"@supabase/node-fetch" "^2.6.14"

"@supabase/realtime-js@2.10.2":
version "2.10.2"
resolved "https://registry.yarnpkg.com/@supabase/realtime-js/-/realtime-js-2.10.2.tgz#c2b42d17d723d2d2a9146cfad61dc3df1ce3127e"
integrity sha512-qyCQaNg90HmJstsvr2aJNxK2zgoKh9ZZA8oqb7UT2LCh3mj9zpa3Iwu167AuyNxsxrUE8eEJ2yH6wLCij4EApA==
dependencies:
"@supabase/node-fetch" "^2.6.14"
"@types/phoenix" "^1.5.4"
"@types/ws" "^8.5.10"
ws "^8.14.2"

"@supabase/storage-js@2.7.0":
version "2.7.0"
resolved "https://registry.yarnpkg.com/@supabase/storage-js/-/storage-js-2.7.0.tgz#9ff322d2c3b141087aa34115cf14205e4980ce75"
integrity sha512-iZenEdO6Mx9iTR6T7wC7sk6KKsoDPLq8rdu5VRy7+JiT1i8fnqfcOr6mfF2Eaqky9VQzhP8zZKQYjzozB65Rig==
dependencies:
"@supabase/node-fetch" "^2.6.14"

"@supabase/supabase-js@^2.45.3":
version "2.45.3"
resolved "https://registry.yarnpkg.com/@supabase/supabase-js/-/supabase-js-2.45.3.tgz#d32b7a7b379958a10dcce32af1182f82b5b82218"
integrity sha512-4wAux6cuVMrdH/qUjKn6p3p3L9AtAO3Une6ojIrtpCj1RaXKVoyIATiacSRAI+pKff6XZBVCGC29v+z4Jo/uSw==
dependencies:
"@supabase/auth-js" "2.65.0"
"@supabase/functions-js" "2.4.1"
"@supabase/node-fetch" "2.6.15"
"@supabase/postgrest-js" "1.15.8"
"@supabase/realtime-js" "2.10.2"
"@supabase/storage-js" "2.7.0"

"@tsconfig/node10@^1.0.7":
version "1.0.11"
resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.11.tgz#6ee46400685f130e278128c7b38b7e031ff5b2f2"
Expand Down Expand Up @@ -1434,11 +1491,23 @@
resolved "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz"
integrity sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==

"@types/phoenix@^1.5.4":
version "1.6.5"
resolved "https://registry.yarnpkg.com/@types/phoenix/-/phoenix-1.6.5.tgz#5654e14ec7ad25334a157a20015996b6d7d2075e"
integrity sha512-xegpDuR+z0UqG9fwHqNoy3rI7JDlvaPh2TY47Fl80oq6g+hXT+c/LEuE43X48clZ6lOfANl5WrPur9fYO1RJ/w==

"@types/stack-utils@^2.0.0":
version "2.0.3"
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8"
integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==

"@types/ws@^8.5.10":
version "8.5.12"
resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.12.tgz#619475fe98f35ccca2a2f6c137702d85ec247b7e"
integrity sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==
dependencies:
"@types/node" "*"

"@types/yargs-parser@*":
version "21.0.3"
resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15"
Expand Down Expand Up @@ -5522,6 +5591,11 @@ tr46@^1.0.1:
dependencies:
punycode "^2.1.0"

tr46@~0.0.3:
version "0.0.3"
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==

tree-kill@^1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc"
Expand Down Expand Up @@ -5810,11 +5884,24 @@ wcwidth@^1.0.1:
dependencies:
defaults "^1.0.3"

webidl-conversions@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==

webidl-conversions@^4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==

whatwg-url@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"
integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==
dependencies:
tr46 "~0.0.3"
webidl-conversions "^3.0.0"

whatwg-url@^7.0.0:
version "7.1.0"
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06"
Expand Down Expand Up @@ -5914,6 +6001,11 @@ write-file-atomic@^4.0.2:
imurmurhash "^0.1.4"
signal-exit "^3.0.7"

ws@^8.14.2:
version "8.18.0"
resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc"
integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==

xml@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/xml/-/xml-1.0.1.tgz#78ba72020029c5bc87b8a81a3cfcd74b4a2fc1e5"
Expand Down
Loading