Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion bridge-starter-node/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,14 @@
"dependencies": {
"axios": "^1.15.2",
"dotenv": "^17.4.2",
"express": "^5.2.1"
"express": "^5.2.1",
"pino": "^9.6.0",
"pino-pretty": "^13.0.0"
},
"devDependencies": {
"@types/express": "^5.0.6",
"@types/node": "^25.6.0",
"@types/pino": "^7.0.5",
"ts-node-dev": "^2.0.0",
"typescript": "^6.0.3"
}
Expand Down
8 changes: 6 additions & 2 deletions bridge-starter-node/src/app.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import express, { Request, Response } from "express";
import webhookRoutes from "./routes/webhook";
import { config } from "./config/env";
import { createChildLogger } from "./config/logger";
import { requestLogger } from "./middleware/requestLogger";

const logger = createChildLogger("app");
const app = express();

app.use(express.json());
app.use(requestLogger);

app.get("/", (req: Request, res: Response) => {
res.send("Bridge Starter API running 🚀");
Expand All @@ -13,5 +17,5 @@ app.get("/", (req: Request, res: Response) => {
app.use("/api", webhookRoutes);

app.listen(config.port, () => {
console.log(`Server running on port ${config.port}`);
});
logger.info({ port: config.port }, "Server started");
});
31 changes: 31 additions & 0 deletions bridge-starter-node/src/config/logger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import pino from "pino";

const isDev = process.env.NODE_ENV !== "production";

export const logger = pino({
level: process.env.LOG_LEVEL || "info",
transport: isDev
? {
target: "pino-pretty",
options: {
colorize: true,
translateTime: "SYS:standard",
ignore: "pid,hostname",
},
}
: undefined,
formatters: {
level(label: string) {
return { level: label };
},
},
serializers: {
err: pino.stdSerializers.err,
req: pino.stdSerializers.req,
res: pino.stdSerializers.res,
},
});

export function createChildLogger(name: string) {
return logger.child({ module: name });
}
23 changes: 23 additions & 0 deletions bridge-starter-node/src/middleware/requestLogger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Request, Response, NextFunction } from "express";
import { createChildLogger } from "../config/logger";

const logger = createChildLogger("http");

export function requestLogger(req: Request, res: Response, next: NextFunction) {
const start = Date.now();

res.on("finish", () => {
const duration = Date.now() - start;
logger.info(
{
method: req.method,
url: req.url,
statusCode: res.statusCode,
durationMs: duration,
},
"Request completed"
);
});

next();
}
12 changes: 7 additions & 5 deletions bridge-starter-node/src/routes/webhook.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { Router, Request, Response } from "express";
import { verifySignature } from "../middleware/verifySignature";
import { WebhookEvent, PaymentData } from "../types/webhook";
import { createChildLogger } from "../config/logger";

const logger = createChildLogger("webhook");
const router = Router();

router.post(
Expand All @@ -10,23 +12,23 @@ router.post(
(req: Request, res: Response) => {
const event = req.body as WebhookEvent<PaymentData>;

console.log("Received webhook:", event);
logger.info({ type: event.type }, "Received webhook");

switch (event.type) {
case "payment.success":
console.log("Payment successful:", event.data);
logger.info({ paymentId: event.data }, "Payment successful");
break;

case "payment.failed":
console.log("Payment failed:", event.data);
logger.warn({ paymentId: event.data }, "Payment failed");
break;

default:
console.log("Unhandled event:", event.type);
logger.warn({ type: event.type }, "Unhandled event type");
}

res.status(200).json({ received: true });
}
);

export default router;
export default router;
13 changes: 9 additions & 4 deletions bridge-starter-node/src/services/bridge.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import axios from "axios";
import { config } from "../config/env";
import { createChildLogger } from "../config/logger";

const logger = createChildLogger("bridge");

interface CreatePaymentPayload {
amount: number;
Expand All @@ -23,16 +26,18 @@ export const createPayment = async (
payload: CreatePaymentPayload
): Promise<CreatePaymentResponse> => {
try {
logger.info({ amount: payload.amount, currency: payload.currency }, "Creating payment");
const response = await client.post<CreatePaymentResponse>(
"/payments",
payload
);
logger.info({ paymentId: response.data.id, status: response.data.status }, "Payment created");
return response.data;
} catch (error: any) {
console.error(
"Bridge API Error:",
error.response?.data || error.message
logger.error(
{ error: error.response?.data || error.message },
"Bridge API error"
);
throw error;
}
};
};
Loading