Create Logger class for debugging
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import Debug from "debug";
|
||||
import { Logger } from "./utils/logger.js";
|
||||
import { Engine } from "@xo-cash/engine";
|
||||
|
||||
import { Config } from "./services/config.js";
|
||||
@@ -22,7 +22,7 @@ type VendingMachineDeps = {
|
||||
|
||||
export class VendingMachine {
|
||||
static async from(config: Config) {
|
||||
const debug = Debug("vending-machine");
|
||||
const debug = new Logger("vending-machine");
|
||||
|
||||
debug("Config: %O", config);
|
||||
|
||||
@@ -65,7 +65,7 @@ export class VendingMachine {
|
||||
const httpService = new HTTPService({
|
||||
routes,
|
||||
config: config.server,
|
||||
debug,
|
||||
debug: new Logger("vending-machine"),
|
||||
});
|
||||
|
||||
debug("Creating vending machine");
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { Debugger as Debug } from "debug";
|
||||
import type { Logger } from '../utils/logger.js';
|
||||
import type { RouteOptions, FastifyRequest, FastifyReply } from "fastify";
|
||||
import type { Engine } from "@xo-cash/engine";
|
||||
import type { Database } from "../services/database/database.js";
|
||||
@@ -8,7 +8,7 @@ import { z } from "zod";
|
||||
export type ItemsRouteDeps = {
|
||||
database: Database;
|
||||
engine: Engine;
|
||||
debug: Debug;
|
||||
debug: Logger;
|
||||
};
|
||||
|
||||
export class ItemsRoute {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { Debugger as Debug } from "debug";
|
||||
import type { Logger } from '../utils/logger.js';
|
||||
import type { RouteOptions, FastifyRequest, FastifyReply } from "fastify";
|
||||
|
||||
import { z } from "zod";
|
||||
@@ -13,7 +13,7 @@ export type OrdersRouteDeps = {
|
||||
database: Database;
|
||||
orderPaymentService: OrderPaymentService;
|
||||
syncServerUrl: string;
|
||||
debug: Debug;
|
||||
debug: Logger;
|
||||
};
|
||||
|
||||
export class OrdersRoute {
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
import { type Debugger } from "debug";
|
||||
import { Logger } from '../../utils/logger.js';
|
||||
|
||||
import DatabaseConstructor from "better-sqlite3";
|
||||
import { Kysely, SqliteDialect } from "kysely";
|
||||
import type { Database as DatabaseTables } from "./tables.js";
|
||||
|
||||
import { z } from "zod";
|
||||
import { debuggerSchema } from "../../types.js";
|
||||
|
||||
export const databaseOptionsSchema = z.object({
|
||||
config: z.object({
|
||||
path: z.string(),
|
||||
}),
|
||||
|
||||
debug: debuggerSchema,
|
||||
debug: z.custom<Logger>(Logger.isLogger, {
|
||||
message: "Expected a Logger instance",
|
||||
}),
|
||||
});
|
||||
|
||||
type DatabaseOptionsInput = z.input<typeof databaseOptionsSchema>;
|
||||
@@ -26,7 +27,7 @@ type DatabaseOptionsInput = z.input<typeof databaseOptionsSchema>;
|
||||
*/
|
||||
export class Database {
|
||||
// Debugger instance used for logging.
|
||||
private readonly debug: Debugger;
|
||||
private readonly debug: Logger;
|
||||
|
||||
// SQLite connection instance.
|
||||
private readonly sqlite: DatabaseConstructor.Database;
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import Debug from "debug";
|
||||
import { z } from "zod";
|
||||
|
||||
import fastify, { type FastifyInstance, type RouteOptions } from "fastify";
|
||||
import cors from "@fastify/cors";
|
||||
|
||||
import { debuggerSchema } from "../types.js";
|
||||
import { Logger } from "../utils/logger.js";
|
||||
|
||||
// Interface to add to our route classes so that we can register them.
|
||||
// NOTE: I hate this pattern. But ExpressJS is odd in that it is structured as a singleton that still needs registration.
|
||||
@@ -33,9 +32,12 @@ export const serverConfigSchema = z.object({
|
||||
});
|
||||
|
||||
// Zod schema for the server debug instance.
|
||||
export const serverDebugSchema = debuggerSchema
|
||||
export const serverDebugSchema = z
|
||||
.custom<Logger>(Logger.isLogger, {
|
||||
message: "Expected a Logger instance",
|
||||
})
|
||||
.optional()
|
||||
.default(Debug("vending-machine"));
|
||||
.default(new Logger("vending-machine"));
|
||||
|
||||
// Zod schema for the HTTP service options.
|
||||
export const HTTPOptions = z.object({
|
||||
@@ -61,7 +63,7 @@ export class HTTPService {
|
||||
private server: FastifyInstance;
|
||||
|
||||
// Private properties.
|
||||
private debug: debug.Debugger;
|
||||
private debug: Logger;
|
||||
private config: HTTPServiceOptions["config"];
|
||||
private routes: HTTPServiceOptions["routes"];
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { Debugger } from "debug";
|
||||
import type { Logger } from '../utils/logger.js';
|
||||
import type { Engine } from "@xo-cash/engine";
|
||||
import type { XOInvitation, XOInvitationCommit } from "@xo-cash/types";
|
||||
|
||||
@@ -11,7 +11,7 @@ export type OrderInvitationTrackerDeps = {
|
||||
database: Database;
|
||||
orderId: string;
|
||||
invitation: XOInvitation;
|
||||
debug: Debugger;
|
||||
debug: Logger;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import type { Debugger } from "debug";
|
||||
import type { Logger } from '../utils/logger.js';
|
||||
import type { Engine } from "@xo-cash/engine";
|
||||
import { serializeInvitation } from "@xo-cash/engine";
|
||||
import { vendingMachineTemplate } from "../templates/vending-machine.js";
|
||||
|
||||
import type { Config } from "./config.js";
|
||||
import type { Database } from "./database/database.js";
|
||||
import type { ItemsTable } from "./database/tables.js";
|
||||
import { InvitationSyncClient } from "./invitation-sync-client.js";
|
||||
import { OrderInvitationTracker } from "./order-invitation-tracker.js";
|
||||
|
||||
@@ -40,7 +39,7 @@ export type OrderPaymentServiceDeps = {
|
||||
database: Database;
|
||||
config: Config;
|
||||
syncClient: InvitationSyncClient;
|
||||
debug: Debugger;
|
||||
debug: Logger;
|
||||
templateIdentifier: string;
|
||||
trackers: Map<string, OrderInvitationTracker>;
|
||||
};
|
||||
@@ -55,7 +54,7 @@ export class OrderPaymentService {
|
||||
engine: Engine;
|
||||
database: Database;
|
||||
config: Config;
|
||||
debug: Debugger;
|
||||
debug: Logger;
|
||||
trackers: Map<string, OrderInvitationTracker>;
|
||||
}): Promise<OrderPaymentService> {
|
||||
const { templateIdentifier } = await deps.engine.importTemplate(
|
||||
|
||||
18
src/types.ts
18
src/types.ts
@@ -1,18 +0,0 @@
|
||||
import { type Debugger } from "debug";
|
||||
import { z } from "zod";
|
||||
|
||||
export const isDebugger = (value: unknown): value is Debugger => {
|
||||
if (typeof value !== "function") return false;
|
||||
|
||||
const candidate = value as Partial<Debugger>;
|
||||
|
||||
return (
|
||||
typeof candidate.namespace === "string" &&
|
||||
typeof candidate.extend === "function" &&
|
||||
typeof candidate.enabled === "boolean"
|
||||
);
|
||||
};
|
||||
|
||||
export const debuggerSchema = z.custom<Debugger>(isDebugger, {
|
||||
message: "Expected a debug.Debugger instance",
|
||||
});
|
||||
57
src/utils/logger.ts
Normal file
57
src/utils/logger.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import Debug, { type Debugger } from "debug";
|
||||
|
||||
type LogHandler = {
|
||||
(...args: Parameters<Debugger>): void;
|
||||
extend: (namespace: string) => LogHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Declares that Logger instances may also be invoked as functions.
|
||||
*/
|
||||
export interface Logger {
|
||||
(...args: unknown[]): void;
|
||||
}
|
||||
|
||||
export class Logger {
|
||||
public readonly namespace!: string;
|
||||
|
||||
private readonly handler!: LogHandler;
|
||||
|
||||
public constructor(
|
||||
namespace: string,
|
||||
handler: LogHandler = Debug(namespace),
|
||||
) {
|
||||
const logger = ((...args: Parameters<Debugger>): void => {
|
||||
handler(...args);
|
||||
}) as Logger;
|
||||
|
||||
/*
|
||||
* This makes `logger instanceof Logger` true and provides
|
||||
* access to instance methods such as `extend`.
|
||||
*/
|
||||
Object.setPrototypeOf(logger, new.target.prototype);
|
||||
|
||||
Object.defineProperties(logger, {
|
||||
namespace: {
|
||||
value: namespace,
|
||||
enumerable: true,
|
||||
},
|
||||
handler: {
|
||||
value: handler,
|
||||
},
|
||||
});
|
||||
|
||||
return logger;
|
||||
}
|
||||
|
||||
public extend(childNamespace: string): Logger {
|
||||
return new Logger(
|
||||
childNamespace,
|
||||
this.handler.extend(childNamespace),
|
||||
);
|
||||
}
|
||||
|
||||
static isLogger(value: unknown): value is Logger {
|
||||
return value instanceof Logger;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user