From 58274870cb29f6be8dd84d4916211924e102a748 Mon Sep 17 00:00:00 2001 From: Lukasz Kosiak Date: Mon, 25 May 2026 21:50:24 +0200 Subject: [PATCH] pino logging added to governance-api --- products/governance-api/Dockerfile | 2 +- products/governance-api/lib/app.ts | 12 ++ products/governance-api/lib/logger.ts | 3 + products/governance-api/lib/routes/message.ts | 29 ++- products/governance-api/lib/routes/spaces.ts | 115 +++++++----- products/governance-api/lib/server.ts | 15 +- products/governance-api/lib/utils/pin-ipfs.ts | 5 +- .../lib/zilliqa/custom-fetch.ts | 14 +- products/governance-api/package.json | 6 +- products/governance-api/run.sh | 10 +- products/governance-api/yarn.lock | 173 +++++++++++++++++- 11 files changed, 305 insertions(+), 79 deletions(-) create mode 100644 products/governance-api/lib/logger.ts diff --git a/products/governance-api/Dockerfile b/products/governance-api/Dockerfile index 27153cffc..e51eb3f05 100644 --- a/products/governance-api/Dockerfile +++ b/products/governance-api/Dockerfile @@ -3,7 +3,7 @@ FROM node:20 WORKDIR /app COPY package.json yarn.lock ./ -RUN npm install +RUN yarn install COPY . . diff --git a/products/governance-api/lib/app.ts b/products/governance-api/lib/app.ts index ada706e39..00db00873 100644 --- a/products/governance-api/lib/app.ts +++ b/products/governance-api/lib/app.ts @@ -1,10 +1,22 @@ import express from "express"; import * as bodyParser from "body-parser"; import errorhandler from "strong-error-handler"; +import pinoHttp from "pino-http"; import router from "./routes"; +import { logger } from "./logger"; export const app = express(); +app.use( + pinoHttp({ + logger, + customLogLevel: (_req, res, _err) => { + if (res.statusCode >= 400) return "error"; + return "info"; + }, + }) +); + // middleware for parsing application/x-www-form-urlencoded app.use(bodyParser.urlencoded({ extended: true })); diff --git a/products/governance-api/lib/logger.ts b/products/governance-api/lib/logger.ts new file mode 100644 index 000000000..c6ce2a7b8 --- /dev/null +++ b/products/governance-api/lib/logger.ts @@ -0,0 +1,3 @@ +const rootLogger = require('pino')() + +export const logger = rootLogger.child({ level: "info" }); diff --git a/products/governance-api/lib/routes/message.ts b/products/governance-api/lib/routes/message.ts index 58fd9798d..b3ac9d9b1 100644 --- a/products/governance-api/lib/routes/message.ts +++ b/products/governance-api/lib/routes/message.ts @@ -83,7 +83,7 @@ const proposal = (res: any, msg: any) => { }); } }; -const vote = async (res: any, msg: any, ts: string) => { +const vote = async (res: any, msg: any, ts: string, log: any) => { if (msg.type !== "vote") { return null; } @@ -118,6 +118,7 @@ const vote = async (res: any, msg: any, ts: string) => { }); if (!proposal) { + log.error({ error_code: ErrorCodes.INCORRECT_PROPOSAL_FORMAT, token: msg.token }, "Proposal not found"); return res.status(400).json({ code: ErrorCodes.INCORRECT_PROPOSAL_FORMAT, error_description: "incorect vote proposal", @@ -126,6 +127,7 @@ const vote = async (res: any, msg: any, ts: string) => { const payload = JSON.parse(proposal.payload); if (Number(ts) > Number(payload.end) || Number(payload.start) > Number(ts)) { + log.error({ error_code: ErrorCodes.INCORRECT_VOTE_FORMAT, address: msg.address }, "Not in voting window"); return res.status(400).json({ code: ErrorCodes.INCORRECT_VOTE_FORMAT, error_description: "not in voting window", @@ -134,12 +136,14 @@ const vote = async (res: any, msg: any, ts: string) => { }; message.post("/message", async (req, res) => { + const log = (req as any).log; try { const body = req.body; const msg = JSON.parse(body.msg); const ts = (Date.now() / 1e3).toFixed(); if (!body || !body.address || !body.msg || !body.sig) { + log.error({ error_code: ErrorCodes.INCORRECT_DATA, address: body && body.address }, "incorrect message body"); return res.status(400).json({ code: ErrorCodes.INCORRECT_DATA, error_description: "incorect message body", @@ -148,6 +152,7 @@ message.post("/message", async (req, res) => { const spaceKey = body.space; if (!spaceKey || !spaces[spaceKey]) { + log.error({ error_code: ErrorCodes.UNKNOWN_SPACE, address: body && body.address }, "unknown space"); return res.status(400).json({ code: ErrorCodes.UNKNOWN_SPACE, error_description: "unknown space", @@ -155,6 +160,7 @@ message.post("/message", async (req, res) => { } if (spaces[spaceKey].token !== msg.token) { + log.error({ error_code: ErrorCodes.UNKNOWN_SPACE, address: body && body.address }, "token does not match space"); return res.status(400).json({ code: ErrorCodes.UNKNOWN_SPACE, error_description: "token does not match space", @@ -164,6 +170,7 @@ message.post("/message", async (req, res) => { msg.timestamp = Number(msg.timestamp); if (!msg.timestamp || isNaN(msg.timestamp) || msg.timestamp > ts + 30) { + log.error({ error_code: ErrorCodes.INCORRECT_DATA, address: body && body.address }, "wrong timestamp"); return res.status(400).json({ code: ErrorCodes.INCORRECT_DATA, error_description: "wrong timestamp", @@ -171,6 +178,7 @@ message.post("/message", async (req, res) => { } if (!msg.version || msg.version !== pkg.version) { + log.error({ error_code: ErrorCodes.INCORRECT_VER, address: body && body.address }, "incorrect version"); return res.status(400).json({ code: ErrorCodes.INCORRECT_VER, error_description: "incorrect version", @@ -178,6 +186,7 @@ message.post("/message", async (req, res) => { } if (!msg.type || !["proposal", "vote"].includes(msg.type)) { + log.error({ error_code: ErrorCodes.INCORRECT_TYPE, address: body && body.address }, "incorrect type"); return res.status(400).json({ code: ErrorCodes.INCORRECT_TYPE, error_description: "incorrect type", @@ -208,14 +217,17 @@ message.post("/message", async (req, res) => { } if (!checked) throw new Error('signature mismatch'); } catch (err) { + log.error({ error_code: ErrorCodes.INCORRECT_SIGNATURE, address: body.address }, "Signature verification failed"); return res.status(400).json({ code: ErrorCodes.INCORRECT_SIGNATURE, error_description: "incorrect signature", }); } + log.info({ address: body.address, sigType: body.sigType || "schnorr" }, "Signature verified"); + proposal(res, msg); - await vote(res, msg, ts); + await vote(res, msg, ts, log); const space = spaceKey; let authorIpfsRes: any | null = null; @@ -230,10 +242,13 @@ message.post("/message", async (req, res) => { base16owner ); + log.info({ token: base16Token, address: base16owner, userBalance }, "Zilliqa liquidity fetched"); + const _balance = new BN(userBalance); const _minGZIL = new BN("30000000000000000"); if (msg.token == gZIL && _balance.lt(_minGZIL)) { + log.error({ error_code: ErrorCodes.MIN_BALANCE_ERROR, balance: _balance.toString(), threshold: _minGZIL.toString() }, "Balance below minimum gZIL"); return res.status(400).json({ code: ErrorCodes.MIN_BALANCE_ERROR, error_description: @@ -260,6 +275,7 @@ message.post("/message", async (req, res) => { payload: JSON.stringify(msg.payload), sig: JSON.stringify(body.sig), }); + log.info({ type: msg.type, ipfsHash: authorIpfsRes, address: body.address }, "DB record created"); } if (msg.type === "vote") { @@ -281,17 +297,14 @@ message.post("/message", async (req, res) => { payload: JSON.stringify(msg.payload), sig: JSON.stringify(body.sig), }); + log.info({ type: msg.type, ipfsHash: authorIpfsRes, address: body.address }, "DB record created"); } - console.log( - `Address "${body.address}"\n`, - `Token "${msg.token}"\n`, - `Type "${msg.type}"\n`, - `IPFS hash "${authorIpfsRes}"` - ); + log.info({ address: body.address, token: msg.token, type: msg.type, ipfsHash: authorIpfsRes }, "Message processed successfully"); return res.json({ ipfsHash: authorIpfsRes }); } catch (err) { + log.error({ err, error_code: 500 }, "Unhandled error in message handler"); return res.status(400).json({ code: 500, error_description: err.message, diff --git a/products/governance-api/lib/routes/spaces.ts b/products/governance-api/lib/routes/spaces.ts index 1d35d0bde..5f19b6e74 100644 --- a/products/governance-api/lib/routes/spaces.ts +++ b/products/governance-api/lib/routes/spaces.ts @@ -2,6 +2,7 @@ import { Router } from "express"; import fromentries from "object.fromentries"; import spaces from "@snapshot-labs/snapshot-spaces"; import { Message } from "../models"; +import { logger } from "../logger"; export const spacesRouter = Router(); @@ -13,61 +14,77 @@ spacesRouter.get("/spaces/:key?", (req, res) => { spacesRouter.get("/:space/proposals", async (req, res) => { const { space } = req.params; - const messages = await Message.findAll({ - where: { - space, - type: "proposal", - }, - order: [["timestamp", "DESC"]], - }); - const spaces = messages.map((message) => { - return [ - message.id, - { - address: message.address, - msg: { - version: message.version, - timestamp: String(message.timestamp), - token: message.token, - type: message.type, - payload: JSON.parse(message.payload), - }, - sig: message.sig, - authorIpfsHash: message.author_ipfs_hash, + try { + const messages = await Message.findAll({ + where: { + space, + type: "proposal", }, - ]; - }); + order: [["timestamp", "DESC"]], + }); + const spaces = messages.map((message) => { + return [ + message.id, + { + address: message.address, + msg: { + version: message.version, + timestamp: String(message.timestamp), + token: message.token, + type: message.type, + payload: JSON.parse(message.payload), + }, + sig: message.sig, + authorIpfsHash: message.author_ipfs_hash, + }, + ]; + }); - return res.status(201).json(fromentries(spaces)); + return res.status(201).json(fromentries(spaces)); + } catch (err) { + logger.error( + { err, space: req.params.space, error_code: "DB_QUERY_FAILED" }, + "Failed to fetch proposals" + ); + return res.status(500).json({ error: "Internal server error" }); + } }); spacesRouter.get("/:space/proposal/:id", async (req, res) => { const { space, id } = req.params; - const messages = await Message.findAll({ - where: { - space, - proposal_id: id, - type: "vote", - }, - order: [["timestamp", "DESC"]], - }); - const spaces = messages.map((message) => { - return [ - message.address, - { - address: message.address, - msg: { - version: message.version, - timestamp: message.timestamp.toString(), - token: message.token, - type: message.type, - payload: JSON.parse(message.payload), - }, - sig: message.sig, - authorIpfsHash: message.author_ipfs_hash, + try { + const messages = await Message.findAll({ + where: { + space, + proposal_id: id, + type: "vote", }, - ]; - }); + order: [["timestamp", "DESC"]], + }); + const spaces = messages.map((message) => { + return [ + message.address, + { + address: message.address, + msg: { + version: message.version, + timestamp: message.timestamp.toString(), + token: message.token, + type: message.type, + payload: JSON.parse(message.payload), + }, + sig: message.sig, + authorIpfsHash: message.author_ipfs_hash, + }, + ]; + }); - return res.status(201).json(fromentries(spaces)); + return res.status(201).json(fromentries(spaces)); + } catch (err) { + logger.error( + { err, space: req.params.space, id: req.params.id, error_code: "DB_QUERY_FAILED" }, + "Failed to fetch proposal votes" + ); + return res.status(500).json({ error: "Internal server error" }); + } }); diff --git a/products/governance-api/lib/server.ts b/products/governance-api/lib/server.ts index 18488f8a8..216f01c74 100644 --- a/products/governance-api/lib/server.ts +++ b/products/governance-api/lib/server.ts @@ -1,13 +1,20 @@ import { createServer } from "http"; import { app } from "./app"; +import { logger } from "./logger"; import { sequelizeRun } from "./sequelize"; const port = process.env.PORT || 3000; (async () => { - await sequelizeRun(); + try { + await sequelizeRun(); + logger.info("Database synced"); - createServer(app).listen(port, () => - console.info(`Server running on port ${port}`) - ); + createServer(app).listen(port, () => + logger.info({ port }, "Server started") + ); + } catch (err) { + logger.error({ err }, "Startup failed"); + process.exit(1); + } })(); diff --git a/products/governance-api/lib/utils/pin-ipfs.ts b/products/governance-api/lib/utils/pin-ipfs.ts index d7549ba54..a02fd9194 100644 --- a/products/governance-api/lib/utils/pin-ipfs.ts +++ b/products/governance-api/lib/utils/pin-ipfs.ts @@ -1,5 +1,6 @@ import fetch from "node-fetch"; import pinataSDK from "@pinata/sdk"; +import { logger } from "../logger"; export async function pinJson(body: object): Promise { if (process.env.IPFS_API_URL) { @@ -11,6 +12,7 @@ export async function pinJson(body: object): Promise { String(process.env.PINATA_SECRET_API_KEY) ); const result = await pinata.pinJSONToIPFS(body); + logger.info({ ipfsHash: result.IpfsHash }, "IPFS pin succeeded (Pinata)"); return result.IpfsHash; } @@ -39,12 +41,13 @@ async function pinToLocalNode(body: object): Promise { ); if (!response.ok) { + logger.error({ status: response.status }, "IPFS pin failed"); throw new Error( `IPFS add failed: ${response.status} ${await response.text()}` ); } const data = (await response.json()) as { Hash: string }; - console.log("IPFS pin success", data.Hash); + logger.info({ ipfsHash: data.Hash }, "IPFS pin succeeded (local node)"); return data.Hash; } diff --git a/products/governance-api/lib/zilliqa/custom-fetch.ts b/products/governance-api/lib/zilliqa/custom-fetch.ts index cbf82adc1..3a3be7e78 100644 --- a/products/governance-api/lib/zilliqa/custom-fetch.ts +++ b/products/governance-api/lib/zilliqa/custom-fetch.ts @@ -1,6 +1,7 @@ // import { cloneDeep } from 'lodash'; import BN from "bn.js"; import { RPCMethod } from "@zilliqa-js/core"; +import { logger } from "../logger"; export enum TokenFields { TotalSupply = "total_supply", @@ -64,7 +65,13 @@ export class blockchain { jsonrpc: `2.0`, }, ]; - const res = await this._send(batch); + let res: object[]; + try { + res = await this._send(batch); + } catch (err) { + logger.error({ err, error_code: "ZILLIQA_RPC_FAILED" }, "Zilliqa RPC call failed"); + throw err; + } let tokenBalances = res[4]["result"][TokenFields.Balances]; const totalSupply = res[5]["result"][TokenFields.TotalSupply]; @@ -73,6 +80,7 @@ export class blockchain { const userBalance = tokenBalances[address]; + logger.info({ token, address, userBalance }, "Zilliqa liquidity fetched"); return { balances: tokenBalances, totalSupply, @@ -121,7 +129,7 @@ export class blockchain { } } } catch (err) { - console.log("parse-xcad", err); + logger.error({ err, error_code: "PARSE_XCAD_FAILED" }, "XCAD parse error"); } return tokenBalances; @@ -163,7 +171,7 @@ export class blockchain { } } } catch (err) { - console.log("zilswap-parse", err); + logger.error({ err, error_code: "PARSE_ZILSWAP_FAILED" }, "ZilSwap parse error"); } return tokenBalances; diff --git a/products/governance-api/package.json b/products/governance-api/package.json index 336c5c5ab..d85f45ff7 100644 --- a/products/governance-api/package.json +++ b/products/governance-api/package.json @@ -28,6 +28,8 @@ "object.fromentries": "^2.0.2", "pg": "^8.4.2", "pinata": "^0.0.1", + "pino": "^10.3.1", + "pino-http": "^11.0.0", "reflect-metadata": "^0.1.13", "require-context": "^1.1.0", "sequelize": "^5.12.2", @@ -39,9 +41,11 @@ "@types/express": "^4.17.8", "@types/node": "^14.14.5", "@types/object.fromentries": "^2.0.0", + "@types/pino-http": "^6.1.0", + "pino-pretty": "^13.1.3", "sequelize-cli": "^6.2.0", "ts-node": "^10.2.1", "tslint": "^6.1.3", - "typescript": "3.3.3" + "typescript": "3.9.10" } } diff --git a/products/governance-api/run.sh b/products/governance-api/run.sh index b96d2e6aa..31db24b3a 100644 --- a/products/governance-api/run.sh +++ b/products/governance-api/run.sh @@ -1,6 +1,6 @@ #!/bin/bash -echo "Postgres Database: POSTGRES_DB" +echo "Postgres Database: $POSTGRES_DB" echo "Postgres Host: $POSTGRES_HOST" echo "Postgres username: $POSTGRES_USER" @@ -8,7 +8,7 @@ echo "Environment is $DEPLOY_ENV" echo "run script $SCRIPT" echo "Callback: $CALLBACK" date -npm run db:create -npm run db:migrate -npm run db:seed -npm run $SCRIPT +yarn db:create +yarn db:migrate +yarn db:seed +yarn $SCRIPT diff --git a/products/governance-api/yarn.lock b/products/governance-api/yarn.lock index cb4ad254a..4d68ef40a 100644 --- a/products/governance-api/yarn.lock +++ b/products/governance-api/yarn.lock @@ -99,6 +99,11 @@ is-ipfs "^0.6.0" recursive-fs "^1.1.2" +"@pinojs/redact@^0.4.0": + version "0.4.0" + resolved "https://registry.npmjs.org/@pinojs/redact/-/redact-0.4.0.tgz#c3de060dd12640dcc838516aa2a6803cc7b2e9d6" + integrity sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg== + "@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf" @@ -252,6 +257,13 @@ resolved "https://registry.yarnpkg.com/@types/object.fromentries/-/object.fromentries-2.0.1.tgz#7b1bc05244e67d4b4ad46f2b6d5ad5bd035f3bdb" integrity sha512-lP1hS37U5G83Z5xzyEIMIBKjWlAwu2AnZOHCsWDPitY7lmOBDqSiVtdJZVeUJdGEbcJZBG3sif52XHf7WvKrgQ== +"@types/pino-http@^6.1.0": + version "6.1.0" + resolved "https://registry.npmjs.org/@types/pino-http/-/pino-http-6.1.0.tgz#3bdda94b4cda0481c907fb9f2bb7502c8ff538d4" + integrity sha512-rjPOSk2yI0714Pi8LdjIhDynXWqOvswmjRiTHj/1TOh1+0R26aKJ8vAVZRc4Ky5dQ5M5Bly1vrV/Klew6lThkA== + dependencies: + pino-http "*" + "@types/qs@*": version "6.9.7" resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" @@ -531,6 +543,11 @@ asynckit@^0.4.0: resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= +atomic-sleep@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz#eb85b77a601fc932cfe432c5acd364a9e2c9075b" + integrity sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ== + axios@^0.21.1: version "0.21.4" resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" @@ -891,6 +908,11 @@ color-support@^1.1.2, color-support@^1.1.3: resolved "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== +colorette@^2.0.7: + version "2.0.20" + resolved "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" + integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== + combined-stream@^1.0.6: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" @@ -1019,6 +1041,11 @@ data-uri-to-buffer@^4.0.0: resolved "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz#d8feb2b2881e6a4f58c2e08acfd0e2834e26222e" integrity sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A== +dateformat@^4.6.3: + version "4.6.3" + resolved "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz#556fa6497e5217fedb78821424f8a1c22fa3f4b5" + integrity sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA== + debug@2.6.9, debug@^2.2.0: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -1358,7 +1385,12 @@ ext@^1.1.2: dependencies: type "^2.5.0" -fast-safe-stringify@^2.0.6: +fast-copy@^4.0.0: + version "4.0.3" + resolved "https://registry.npmjs.org/fast-copy/-/fast-copy-4.0.3.tgz#935adef81c26276dcbe8892347af307b5090206a" + integrity sha512-58apWr0GUiDFM8+3afrO6eYwJBn9ZAhDOzG3L+/9llab/haCARS2UIfffmOurYLwbgDRs8n0rfr6qAAPEAuAQw== + +fast-safe-stringify@^2.0.6, fast-safe-stringify@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== @@ -1489,7 +1521,7 @@ gauge@^4.0.3: strip-ansi "^6.0.1" wide-align "^1.1.5" -get-caller-file@^2.0.1: +get-caller-file@^2.0.1, get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== @@ -1636,6 +1668,11 @@ hdkey@^1.1.0: safe-buffer "^5.1.1" secp256k1 "^3.0.1" +help-me@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz#b1ebe63b967b74060027c2ac61f9be12d354a6f6" + integrity sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg== + hmac-drbg@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" @@ -1938,6 +1975,11 @@ jake@^10.8.5: filelist "^1.0.4" minimatch "^3.1.2" +joycon@^3.1.1: + version "3.1.1" + resolved "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz#bce8596d6ae808f8b68168f5fc69280996894f03" + integrity sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw== + js-beautify@^1.8.8: version "1.14.0" resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.14.0.tgz#2ce790c555d53ce1e3d7363227acf5dc69024c2d" @@ -2199,7 +2241,7 @@ minimatch@^5.0.1: dependencies: brace-expansion "^2.0.1" -minimist@^1.2.5: +minimist@^1.2.5, minimist@^1.2.6: version "1.2.8" resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== @@ -2518,6 +2560,11 @@ object.fromentries@^2.0.2: define-properties "^1.1.3" es-abstract "^1.19.1" +on-exit-leak-free@^2.1.0: + version "2.1.2" + resolved "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz#fed195c9ebddb7d9e4c3842f93f281ac8dadd3b8" + integrity sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA== + on-finished@2.4.1: version "2.4.1" resolved "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" @@ -2686,6 +2733,64 @@ pinata@^0.0.1: resolved "https://registry.yarnpkg.com/pinata/-/pinata-0.0.1.tgz#4614695dd34bc190bfa71dfae2b82f38a327a8b9" integrity sha1-RhRpXdNLwZC/px364rgvOKMnqLk= +pino-abstract-transport@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-3.0.0.tgz#b21e5f33a297e8c4c915c62b3ce5dd4a87a52c23" + integrity sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg== + dependencies: + split2 "^4.0.0" + +pino-http@*, pino-http@^11.0.0: + version "11.0.0" + resolved "https://registry.npmjs.org/pino-http/-/pino-http-11.0.0.tgz#ebadef4694fc59aadab9be7e5939aea625b4615f" + integrity sha512-wqg5XIAGRRIWtTk8qPGxkbrfiwEWz1lgedVLvhLALudKXvg1/L2lTFgTGPJ4Z2e3qcRmxoFxDuSdMdMGNM6I1g== + dependencies: + get-caller-file "^2.0.5" + pino "^10.0.0" + pino-std-serializers "^7.0.0" + process-warning "^5.0.0" + +pino-pretty@^13.1.3: + version "13.1.3" + resolved "https://registry.npmjs.org/pino-pretty/-/pino-pretty-13.1.3.tgz#2274cccda925dd355c104079a5029f6598d0381b" + integrity sha512-ttXRkkOz6WWC95KeY9+xxWL6AtImwbyMHrL1mSwqwW9u+vLp/WIElvHvCSDg0xO/Dzrggz1zv3rN5ovTRVowKg== + dependencies: + colorette "^2.0.7" + dateformat "^4.6.3" + fast-copy "^4.0.0" + fast-safe-stringify "^2.1.1" + help-me "^5.0.0" + joycon "^3.1.1" + minimist "^1.2.6" + on-exit-leak-free "^2.1.0" + pino-abstract-transport "^3.0.0" + pump "^3.0.0" + secure-json-parse "^4.0.0" + sonic-boom "^4.0.1" + strip-json-comments "^5.0.2" + +pino-std-serializers@^7.0.0: + version "7.1.0" + resolved "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.1.0.tgz#a7b0cd65225f29e92540e7853bd73b07479893fc" + integrity sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw== + +pino@^10.0.0, pino@^10.3.1: + version "10.3.1" + resolved "https://registry.npmjs.org/pino/-/pino-10.3.1.tgz#6552c8f8d8481844c9e452e7bf0be90bff1939ce" + integrity sha512-r34yH/GlQpKZbU1BvFFqOjhISRo1MNx1tWYsYvmj6KIRHSPMT2+yHOEb1SG6NMvRoHRF0a07kCOox/9yakl1vg== + dependencies: + "@pinojs/redact" "^0.4.0" + atomic-sleep "^1.0.0" + on-exit-leak-free "^2.1.0" + pino-abstract-transport "^3.0.0" + pino-std-serializers "^7.0.0" + process-warning "^5.0.0" + quick-format-unescaped "^4.0.3" + real-require "^0.2.0" + safe-stable-stringify "^2.3.1" + sonic-boom "^4.0.1" + thread-stream "^4.0.0" + postgres-array@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-2.0.0.tgz#48f8fce054fbc69671999329b8834b772652d82e" @@ -2708,6 +2813,11 @@ postgres-interval@^1.1.0: dependencies: xtend "^4.0.0" +process-warning@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/process-warning/-/process-warning-5.0.0.tgz#566e0bf79d1dff30a72d8bbbe9e8ecefe8d378d7" + integrity sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA== + promise-inflight@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" @@ -2773,6 +2883,11 @@ qs@6.11.0: dependencies: side-channel "^1.0.4" +quick-format-unescaped@^4.0.3: + version "4.0.4" + resolved "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz#93ef6dd8d3453cbc7970dd614fad4c5954d6b5a7" + integrity sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg== + randombytes@^2.0.1: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" @@ -2804,6 +2919,16 @@ readable-stream@^3.0.0, readable-stream@^3.6.0: string_decoder "^1.1.1" util-deprecate "^1.0.1" +real-require@^0.2.0: + version "0.2.0" + resolved "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz#209632dea1810be2ae063a6ac084fee7e33fba78" + integrity sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg== + +real-require@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/real-require/-/real-require-1.0.0.tgz#e4f0a3737e8060c513b60c2652c58b8ef56bc8a9" + integrity sha512-P4nbQYQfePJxRSmY+v/KINxVucm4NF3p3s7pJveMTtom52FR4YGltUQLB8idDXwDDWW+eYrWDFbuzUnjoWHF7g== + recursive-fs@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/recursive-fs/-/recursive-fs-1.1.2.tgz#1d752e2f1a65d25fb6964109a9dbf83a335f90f0" @@ -2871,6 +2996,11 @@ safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, s resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== +safe-stable-stringify@^2.3.1: + version "2.5.0" + resolved "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz#4ca2f8e385f2831c432a719b108a3bf7af42a1dd" + integrity sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA== + "safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0": version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" @@ -2900,6 +3030,11 @@ secp256k1@^3.0.1: nan "^2.14.0" safe-buffer "^5.1.2" +secure-json-parse@^4.0.0: + version "4.1.0" + resolved "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-4.1.0.tgz#4f1ab41c67a13497ea1b9131bb4183a22865477c" + integrity sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA== + semver@^5.3.0, semver@^5.6.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" @@ -3073,6 +3208,13 @@ socks@^2.6.2: ip-address "^9.0.5" smart-buffer "^4.2.0" +sonic-boom@^4.0.1: + version "4.2.1" + resolved "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.1.tgz#28598250df4899c0ac572d7e2f0460690ba6a030" + integrity sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q== + dependencies: + atomic-sleep "^1.0.0" + split2@^3.1.1: version "3.2.2" resolved "https://registry.yarnpkg.com/split2/-/split2-3.2.2.tgz#bf2cf2a37d838312c249c89206fd7a17dd12365f" @@ -3080,6 +3222,11 @@ split2@^3.1.1: dependencies: readable-stream "^3.0.0" +split2@^4.0.0: + version "4.2.0" + resolved "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4" + integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg== + sprintf-js@^1.1.3: version "1.1.3" resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz#4914b903a2f8b685d17fdf78a70e917e872e444a" @@ -3178,6 +3325,11 @@ strip-final-newline@^2.0.0: resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== +strip-json-comments@^5.0.2: + version "5.0.3" + resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-5.0.3.tgz#b7304249dd402ee67fd518ada993ab3593458bcf" + integrity sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw== + strong-error-handler@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/strong-error-handler/-/strong-error-handler-4.0.0.tgz#162e13020c7b3fc5d4bc3f69a5cb45ea44232b31" @@ -3232,6 +3384,13 @@ tar@^6.0.2, tar@^6.1.11, tar@^6.1.2: mkdirp "^1.0.3" yallist "^4.0.0" +thread-stream@^4.0.0: + version "4.2.0" + resolved "https://registry.npmjs.org/thread-stream/-/thread-stream-4.2.0.tgz#054063e93baab22363d05b784d6c7e439230cac7" + integrity sha512-e2zZ96wSChazBsbENf/Pcm/4swHt2cEKQ92rhUjkL9GCKiTDJIaTBenjE/m9DXi0QBmTMDkFDdOomUy20A1tDQ== + dependencies: + real-require "^1.0.0" + timers-ext@^0.1.5, timers-ext@^0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/timers-ext/-/timers-ext-0.1.7.tgz#6f57ad8578e07a3fb9f91d9387d65647555e25c6" @@ -3344,10 +3503,10 @@ typedarray-to-buffer@^3.1.5: dependencies: is-typedarray "^1.0.0" -typescript@3.3.3: - version "3.3.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.3.3.tgz#f1657fc7daa27e1a8930758ace9ae8da31403221" - integrity sha512-Y21Xqe54TBVp+VDSNbuDYdGw0BpoR/Q6wo/+35M8PAU0vipahnyduJWirxxdxjsAkS7hue53x2zp8gz7F05u0A== +typescript@3.9.10: + version "3.9.10" + resolved "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz#70f3910ac7a51ed6bef79da7800690b19bf778b8" + integrity sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q== umzug@^2.3.0: version "2.3.0"