From 11efdf32a0828c277569905c4690a9bfacebffaf Mon Sep 17 00:00:00 2001 From: yaroslav8765 Date: Fri, 9 Jan 2026 14:13:31 +0200 Subject: [PATCH 1/7] feat: add pino logger --- adminforth/modules/logger.ts | 25 ++ adminforth/package-lock.json | 433 +++++++++++++++++++++++++++++++++++ adminforth/package.json | 2 + 3 files changed, 460 insertions(+) create mode 100644 adminforth/modules/logger.ts diff --git a/adminforth/modules/logger.ts b/adminforth/modules/logger.ts new file mode 100644 index 000000000..6e89ee183 --- /dev/null +++ b/adminforth/modules/logger.ts @@ -0,0 +1,25 @@ +import pino from 'pino'; +import { PinoPretty } from "pino-pretty"; + +export const logger = pino({ + transport: { + target: 'pino-pretty', + options: { + colorize: true, + ignore: 'pid,hostname', + hideObject: true, + messageFormat: '[{level}] ({layer}) {msg}', + } + }, + level: process.env.HEAVY_DEBUG ? 'trace' : ( process.env.DEBUG_LEVEL || 'info' ) +}); + +export const afLogger = logger.child( + { layer: 'adminforth' }, + { level: process.env.HEAVY_DEBUG ? 'trace' : ( process.env.DEBUG_LEVEL || 'info' ) } +); + +export const dbLogger = logger.child( + { layer: 'db' }, + { level: process.env.HEAVY_DEBUG_QUERY ? 'trace' : (process.env.DEBUG_LEVEL_DB_QUERY || 'info') } +); \ No newline at end of file diff --git a/adminforth/package-lock.json b/adminforth/package-lock.json index f8e1fc6e8..8ae3340a3 100644 --- a/adminforth/package-lock.json +++ b/adminforth/package-lock.json @@ -36,6 +36,8 @@ "mysql2": "^3.14.2", "node-fetch": "^3.3.2", "pg": "^8.11.5", + "pino": "^10.1.0", + "pino-pretty": "^13.1.3", "rate-limiter-flexible": "^8.1.0", "recast": "^0.23.11", "ws": "^8.18.0" @@ -623,6 +625,12 @@ "@octokit/openapi-types": "^27.0.0" } }, + "node_modules/@pinojs/redact": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@pinojs/redact/-/redact-0.4.0.tgz", + "integrity": "sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==", + "license": "MIT" + }, "node_modules/@pnpm/config.env-replace": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", @@ -1211,6 +1219,15 @@ "node": ">=4" } }, + "node_modules/atomic-sleep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/aws-ssl-profiles": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/aws-ssl-profiles/-/aws-ssl-profiles-1.1.2.tgz", @@ -1996,6 +2013,15 @@ "node": ">= 12" } }, + "node_modules/dateformat": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", + "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", + "license": "MIT", + "engines": { + "node": "*" + } + }, "node_modules/dayjs": { "version": "1.11.11", "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.11.tgz", @@ -2609,6 +2635,18 @@ ], "license": "MIT" }, + "node_modules/fast-copy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-4.0.2.tgz", + "integrity": "sha512-ybA6PDXIXOXivLJK/z9e+Otk7ve13I4ckBvGO5I2RRmBU1gMHLVDJYEuJYhGwez7YNlYji2M2DvVU+a9mSFDlw==", + "license": "MIT" + }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "license": "MIT" + }, "node_modules/fetch-blob": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", @@ -3052,6 +3090,12 @@ "node": ">= 0.4" } }, + "node_modules/help-me": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", + "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==", + "license": "MIT" + }, "node_modules/highlight.js": { "version": "10.7.3", "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", @@ -3501,6 +3545,15 @@ "jiti": "lib/jiti-cli.mjs" } }, + "node_modules/joycon": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", + "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -4905,6 +4958,7 @@ }, "node_modules/npm/node_modules/@isaacs/cliui": { "version": "8.0.2", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -4921,6 +4975,7 @@ }, "node_modules/npm/node_modules/@isaacs/cliui/node_modules/ansi-regex": { "version": "6.1.0", + "dev": true, "inBundle": true, "license": "MIT", "engines": { @@ -4932,11 +4987,13 @@ }, "node_modules/npm/node_modules/@isaacs/cliui/node_modules/emoji-regex": { "version": "9.2.2", + "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/@isaacs/cliui/node_modules/string-width": { "version": "5.1.2", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -4953,6 +5010,7 @@ }, "node_modules/npm/node_modules/@isaacs/cliui/node_modules/strip-ansi": { "version": "7.1.0", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -4967,6 +5025,7 @@ }, "node_modules/npm/node_modules/@isaacs/fs-minipass": { "version": "4.0.1", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -4978,11 +5037,13 @@ }, "node_modules/npm/node_modules/@isaacs/string-locale-compare": { "version": "1.1.0", + "dev": true, "inBundle": true, "license": "ISC" }, "node_modules/npm/node_modules/@npmcli/agent": { "version": "3.0.0", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -4998,6 +5059,7 @@ }, "node_modules/npm/node_modules/@npmcli/arborist": { "version": "8.0.0", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -5046,6 +5108,7 @@ }, "node_modules/npm/node_modules/@npmcli/config": { "version": "9.0.0", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -5064,6 +5127,7 @@ }, "node_modules/npm/node_modules/@npmcli/fs": { "version": "4.0.0", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -5075,6 +5139,7 @@ }, "node_modules/npm/node_modules/@npmcli/git": { "version": "6.0.1", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -5094,6 +5159,7 @@ }, "node_modules/npm/node_modules/@npmcli/installed-package-contents": { "version": "3.0.0", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -5109,6 +5175,7 @@ }, "node_modules/npm/node_modules/@npmcli/map-workspaces": { "version": "4.0.2", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -5123,6 +5190,7 @@ }, "node_modules/npm/node_modules/@npmcli/metavuln-calculator": { "version": "8.0.1", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -5138,6 +5206,7 @@ }, "node_modules/npm/node_modules/@npmcli/metavuln-calculator/node_modules/pacote": { "version": "20.0.0", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -5168,6 +5237,7 @@ }, "node_modules/npm/node_modules/@npmcli/name-from-folder": { "version": "3.0.0", + "dev": true, "inBundle": true, "license": "ISC", "engines": { @@ -5176,6 +5246,7 @@ }, "node_modules/npm/node_modules/@npmcli/node-gyp": { "version": "4.0.0", + "dev": true, "inBundle": true, "license": "ISC", "engines": { @@ -5184,6 +5255,7 @@ }, "node_modules/npm/node_modules/@npmcli/package-json": { "version": "6.1.0", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -5201,6 +5273,7 @@ }, "node_modules/npm/node_modules/@npmcli/promise-spawn": { "version": "8.0.2", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -5212,6 +5285,7 @@ }, "node_modules/npm/node_modules/@npmcli/query": { "version": "4.0.0", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -5223,6 +5297,7 @@ }, "node_modules/npm/node_modules/@npmcli/redact": { "version": "3.0.0", + "dev": true, "inBundle": true, "license": "ISC", "engines": { @@ -5231,6 +5306,7 @@ }, "node_modules/npm/node_modules/@npmcli/run-script": { "version": "9.0.2", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -5247,6 +5323,7 @@ }, "node_modules/npm/node_modules/@pkgjs/parseargs": { "version": "0.11.0", + "dev": true, "inBundle": true, "license": "MIT", "optional": true, @@ -5256,6 +5333,7 @@ }, "node_modules/npm/node_modules/@sigstore/protobuf-specs": { "version": "0.3.2", + "dev": true, "inBundle": true, "license": "Apache-2.0", "engines": { @@ -5264,6 +5342,7 @@ }, "node_modules/npm/node_modules/@sigstore/tuf": { "version": "3.0.0", + "dev": true, "inBundle": true, "license": "Apache-2.0", "dependencies": { @@ -5276,6 +5355,7 @@ }, "node_modules/npm/node_modules/@tufjs/canonical-json": { "version": "2.0.0", + "dev": true, "inBundle": true, "license": "MIT", "engines": { @@ -5284,6 +5364,7 @@ }, "node_modules/npm/node_modules/abbrev": { "version": "3.0.0", + "dev": true, "inBundle": true, "license": "ISC", "engines": { @@ -5292,6 +5373,7 @@ }, "node_modules/npm/node_modules/agent-base": { "version": "7.1.1", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -5303,6 +5385,7 @@ }, "node_modules/npm/node_modules/aggregate-error": { "version": "3.1.0", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -5315,6 +5398,7 @@ }, "node_modules/npm/node_modules/ansi-regex": { "version": "5.0.1", + "dev": true, "inBundle": true, "license": "MIT", "engines": { @@ -5323,6 +5407,7 @@ }, "node_modules/npm/node_modules/ansi-styles": { "version": "6.2.1", + "dev": true, "inBundle": true, "license": "MIT", "engines": { @@ -5334,21 +5419,25 @@ }, "node_modules/npm/node_modules/aproba": { "version": "2.0.0", + "dev": true, "inBundle": true, "license": "ISC" }, "node_modules/npm/node_modules/archy": { "version": "1.0.0", + "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/balanced-match": { "version": "1.0.2", + "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/bin-links": { "version": "5.0.0", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -5364,6 +5453,7 @@ }, "node_modules/npm/node_modules/binary-extensions": { "version": "2.3.0", + "dev": true, "inBundle": true, "license": "MIT", "engines": { @@ -5375,6 +5465,7 @@ }, "node_modules/npm/node_modules/brace-expansion": { "version": "2.0.1", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -5383,6 +5474,7 @@ }, "node_modules/npm/node_modules/cacache": { "version": "19.0.1", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -5405,6 +5497,7 @@ }, "node_modules/npm/node_modules/cacache/node_modules/chownr": { "version": "3.0.0", + "dev": true, "inBundle": true, "license": "BlueOak-1.0.0", "engines": { @@ -5413,6 +5506,7 @@ }, "node_modules/npm/node_modules/cacache/node_modules/minizlib": { "version": "3.0.1", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -5425,6 +5519,7 @@ }, "node_modules/npm/node_modules/cacache/node_modules/mkdirp": { "version": "3.0.1", + "dev": true, "inBundle": true, "license": "MIT", "bin": { @@ -5439,6 +5534,7 @@ }, "node_modules/npm/node_modules/cacache/node_modules/p-map": { "version": "7.0.2", + "dev": true, "inBundle": true, "license": "MIT", "engines": { @@ -5450,6 +5546,7 @@ }, "node_modules/npm/node_modules/cacache/node_modules/tar": { "version": "7.4.3", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -5466,6 +5563,7 @@ }, "node_modules/npm/node_modules/cacache/node_modules/yallist": { "version": "5.0.0", + "dev": true, "inBundle": true, "license": "BlueOak-1.0.0", "engines": { @@ -5474,6 +5572,7 @@ }, "node_modules/npm/node_modules/chalk": { "version": "5.3.0", + "dev": true, "inBundle": true, "license": "MIT", "engines": { @@ -5485,6 +5584,7 @@ }, "node_modules/npm/node_modules/chownr": { "version": "2.0.0", + "dev": true, "inBundle": true, "license": "ISC", "engines": { @@ -5493,6 +5593,7 @@ }, "node_modules/npm/node_modules/ci-info": { "version": "4.1.0", + "dev": true, "funding": [ { "type": "github", @@ -5507,6 +5608,7 @@ }, "node_modules/npm/node_modules/cidr-regex": { "version": "4.1.1", + "dev": true, "inBundle": true, "license": "BSD-2-Clause", "dependencies": { @@ -5518,6 +5620,7 @@ }, "node_modules/npm/node_modules/clean-stack": { "version": "2.2.0", + "dev": true, "inBundle": true, "license": "MIT", "engines": { @@ -5526,6 +5629,7 @@ }, "node_modules/npm/node_modules/cli-columns": { "version": "4.0.0", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -5538,6 +5642,7 @@ }, "node_modules/npm/node_modules/cmd-shim": { "version": "7.0.0", + "dev": true, "inBundle": true, "license": "ISC", "engines": { @@ -5546,6 +5651,7 @@ }, "node_modules/npm/node_modules/color-convert": { "version": "2.0.1", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -5557,16 +5663,19 @@ }, "node_modules/npm/node_modules/color-name": { "version": "1.1.4", + "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/common-ancestor-path": { "version": "1.0.1", + "dev": true, "inBundle": true, "license": "ISC" }, "node_modules/npm/node_modules/cross-spawn": { "version": "7.0.6", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -5580,6 +5689,7 @@ }, "node_modules/npm/node_modules/cross-spawn/node_modules/which": { "version": "2.0.2", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -5594,6 +5704,7 @@ }, "node_modules/npm/node_modules/cssesc": { "version": "3.0.0", + "dev": true, "inBundle": true, "license": "MIT", "bin": { @@ -5605,6 +5716,7 @@ }, "node_modules/npm/node_modules/debug": { "version": "4.3.7", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -5621,6 +5733,7 @@ }, "node_modules/npm/node_modules/diff": { "version": "5.2.0", + "dev": true, "inBundle": true, "license": "BSD-3-Clause", "engines": { @@ -5629,16 +5742,19 @@ }, "node_modules/npm/node_modules/eastasianwidth": { "version": "0.2.0", + "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/emoji-regex": { "version": "8.0.0", + "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/encoding": { "version": "0.1.13", + "dev": true, "inBundle": true, "license": "MIT", "optional": true, @@ -5648,6 +5764,7 @@ }, "node_modules/npm/node_modules/env-paths": { "version": "2.2.1", + "dev": true, "inBundle": true, "license": "MIT", "engines": { @@ -5656,16 +5773,19 @@ }, "node_modules/npm/node_modules/err-code": { "version": "2.0.3", + "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/exponential-backoff": { "version": "3.1.1", + "dev": true, "inBundle": true, "license": "Apache-2.0" }, "node_modules/npm/node_modules/fastest-levenshtein": { "version": "1.0.16", + "dev": true, "inBundle": true, "license": "MIT", "engines": { @@ -5674,6 +5794,7 @@ }, "node_modules/npm/node_modules/foreground-child": { "version": "3.3.0", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -5689,6 +5810,7 @@ }, "node_modules/npm/node_modules/fs-minipass": { "version": "3.0.3", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -5700,6 +5822,7 @@ }, "node_modules/npm/node_modules/glob": { "version": "10.4.5", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -5719,11 +5842,13 @@ }, "node_modules/npm/node_modules/graceful-fs": { "version": "4.2.11", + "dev": true, "inBundle": true, "license": "ISC" }, "node_modules/npm/node_modules/hosted-git-info": { "version": "8.0.2", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -5735,11 +5860,13 @@ }, "node_modules/npm/node_modules/http-cache-semantics": { "version": "4.1.1", + "dev": true, "inBundle": true, "license": "BSD-2-Clause" }, "node_modules/npm/node_modules/http-proxy-agent": { "version": "7.0.2", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -5752,6 +5879,7 @@ }, "node_modules/npm/node_modules/https-proxy-agent": { "version": "7.0.5", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -5764,6 +5892,7 @@ }, "node_modules/npm/node_modules/iconv-lite": { "version": "0.6.3", + "dev": true, "inBundle": true, "license": "MIT", "optional": true, @@ -5776,6 +5905,7 @@ }, "node_modules/npm/node_modules/ignore-walk": { "version": "7.0.0", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -5787,6 +5917,7 @@ }, "node_modules/npm/node_modules/imurmurhash": { "version": "0.1.4", + "dev": true, "inBundle": true, "license": "MIT", "engines": { @@ -5795,6 +5926,7 @@ }, "node_modules/npm/node_modules/indent-string": { "version": "4.0.0", + "dev": true, "inBundle": true, "license": "MIT", "engines": { @@ -5803,6 +5935,7 @@ }, "node_modules/npm/node_modules/ini": { "version": "5.0.0", + "dev": true, "inBundle": true, "license": "ISC", "engines": { @@ -5811,6 +5944,7 @@ }, "node_modules/npm/node_modules/init-package-json": { "version": "7.0.2", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -5828,6 +5962,7 @@ }, "node_modules/npm/node_modules/ip-address": { "version": "9.0.5", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -5840,6 +5975,7 @@ }, "node_modules/npm/node_modules/ip-regex": { "version": "5.0.0", + "dev": true, "inBundle": true, "license": "MIT", "engines": { @@ -5851,6 +5987,7 @@ }, "node_modules/npm/node_modules/is-cidr": { "version": "5.1.0", + "dev": true, "inBundle": true, "license": "BSD-2-Clause", "dependencies": { @@ -5862,6 +5999,7 @@ }, "node_modules/npm/node_modules/is-fullwidth-code-point": { "version": "3.0.0", + "dev": true, "inBundle": true, "license": "MIT", "engines": { @@ -5870,11 +6008,13 @@ }, "node_modules/npm/node_modules/isexe": { "version": "2.0.0", + "dev": true, "inBundle": true, "license": "ISC" }, "node_modules/npm/node_modules/jackspeak": { "version": "3.4.3", + "dev": true, "inBundle": true, "license": "BlueOak-1.0.0", "dependencies": { @@ -5889,11 +6029,13 @@ }, "node_modules/npm/node_modules/jsbn": { "version": "1.1.0", + "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/json-parse-even-better-errors": { "version": "4.0.0", + "dev": true, "inBundle": true, "license": "MIT", "engines": { @@ -5902,6 +6044,7 @@ }, "node_modules/npm/node_modules/json-stringify-nice": { "version": "1.1.4", + "dev": true, "inBundle": true, "license": "ISC", "funding": { @@ -5910,6 +6053,7 @@ }, "node_modules/npm/node_modules/jsonparse": { "version": "1.3.1", + "dev": true, "engines": [ "node >= 0.2.0" ], @@ -5918,16 +6062,19 @@ }, "node_modules/npm/node_modules/just-diff": { "version": "6.0.2", + "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/just-diff-apply": { "version": "5.5.0", + "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/libnpmaccess": { "version": "9.0.0", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -5940,6 +6087,7 @@ }, "node_modules/npm/node_modules/libnpmdiff": { "version": "7.0.0", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -5958,6 +6106,7 @@ }, "node_modules/npm/node_modules/libnpmexec": { "version": "9.0.0", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -5978,6 +6127,7 @@ }, "node_modules/npm/node_modules/libnpmfund": { "version": "6.0.0", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -5989,6 +6139,7 @@ }, "node_modules/npm/node_modules/libnpmhook": { "version": "11.0.0", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -6001,6 +6152,7 @@ }, "node_modules/npm/node_modules/libnpmorg": { "version": "7.0.0", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -6013,6 +6165,7 @@ }, "node_modules/npm/node_modules/libnpmpack": { "version": "8.0.0", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -6027,6 +6180,7 @@ }, "node_modules/npm/node_modules/libnpmpublish": { "version": "10.0.1", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -6045,6 +6199,7 @@ }, "node_modules/npm/node_modules/libnpmsearch": { "version": "8.0.0", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -6056,6 +6211,7 @@ }, "node_modules/npm/node_modules/libnpmteam": { "version": "7.0.0", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -6068,6 +6224,7 @@ }, "node_modules/npm/node_modules/libnpmversion": { "version": "7.0.0", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -6083,11 +6240,13 @@ }, "node_modules/npm/node_modules/lru-cache": { "version": "10.4.3", + "dev": true, "inBundle": true, "license": "ISC" }, "node_modules/npm/node_modules/make-fetch-happen": { "version": "14.0.3", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -6109,6 +6268,7 @@ }, "node_modules/npm/node_modules/make-fetch-happen/node_modules/negotiator": { "version": "1.0.0", + "dev": true, "inBundle": true, "license": "MIT", "engines": { @@ -6117,6 +6277,7 @@ }, "node_modules/npm/node_modules/minimatch": { "version": "9.0.5", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -6131,6 +6292,7 @@ }, "node_modules/npm/node_modules/minipass": { "version": "7.1.2", + "dev": true, "inBundle": true, "license": "ISC", "engines": { @@ -6139,6 +6301,7 @@ }, "node_modules/npm/node_modules/minipass-collect": { "version": "2.0.1", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -6150,6 +6313,7 @@ }, "node_modules/npm/node_modules/minipass-fetch": { "version": "4.0.0", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -6166,6 +6330,7 @@ }, "node_modules/npm/node_modules/minipass-fetch/node_modules/minizlib": { "version": "3.0.1", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -6178,6 +6343,7 @@ }, "node_modules/npm/node_modules/minipass-flush": { "version": "1.0.5", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -6189,6 +6355,7 @@ }, "node_modules/npm/node_modules/minipass-flush/node_modules/minipass": { "version": "3.3.6", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -6200,6 +6367,7 @@ }, "node_modules/npm/node_modules/minipass-pipeline": { "version": "1.2.4", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -6211,6 +6379,7 @@ }, "node_modules/npm/node_modules/minipass-pipeline/node_modules/minipass": { "version": "3.3.6", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -6222,6 +6391,7 @@ }, "node_modules/npm/node_modules/minipass-sized": { "version": "1.0.3", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -6233,6 +6403,7 @@ }, "node_modules/npm/node_modules/minipass-sized/node_modules/minipass": { "version": "3.3.6", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -6244,6 +6415,7 @@ }, "node_modules/npm/node_modules/minizlib": { "version": "2.1.2", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -6256,6 +6428,7 @@ }, "node_modules/npm/node_modules/minizlib/node_modules/minipass": { "version": "3.3.6", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -6267,6 +6440,7 @@ }, "node_modules/npm/node_modules/mkdirp": { "version": "1.0.4", + "dev": true, "inBundle": true, "license": "MIT", "bin": { @@ -6278,11 +6452,13 @@ }, "node_modules/npm/node_modules/ms": { "version": "2.1.3", + "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/mute-stream": { "version": "2.0.0", + "dev": true, "inBundle": true, "license": "ISC", "engines": { @@ -6291,6 +6467,7 @@ }, "node_modules/npm/node_modules/node-gyp": { "version": "11.0.0", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -6314,6 +6491,7 @@ }, "node_modules/npm/node_modules/node-gyp/node_modules/chownr": { "version": "3.0.0", + "dev": true, "inBundle": true, "license": "BlueOak-1.0.0", "engines": { @@ -6322,6 +6500,7 @@ }, "node_modules/npm/node_modules/node-gyp/node_modules/minizlib": { "version": "3.0.1", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -6334,6 +6513,7 @@ }, "node_modules/npm/node_modules/node-gyp/node_modules/mkdirp": { "version": "3.0.1", + "dev": true, "inBundle": true, "license": "MIT", "bin": { @@ -6348,6 +6528,7 @@ }, "node_modules/npm/node_modules/node-gyp/node_modules/tar": { "version": "7.4.3", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -6364,6 +6545,7 @@ }, "node_modules/npm/node_modules/node-gyp/node_modules/yallist": { "version": "5.0.0", + "dev": true, "inBundle": true, "license": "BlueOak-1.0.0", "engines": { @@ -6372,6 +6554,7 @@ }, "node_modules/npm/node_modules/nopt": { "version": "8.0.0", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -6386,6 +6569,7 @@ }, "node_modules/npm/node_modules/nopt/node_modules/abbrev": { "version": "2.0.0", + "dev": true, "inBundle": true, "license": "ISC", "engines": { @@ -6394,6 +6578,7 @@ }, "node_modules/npm/node_modules/normalize-package-data": { "version": "7.0.0", + "dev": true, "inBundle": true, "license": "BSD-2-Clause", "dependencies": { @@ -6407,6 +6592,7 @@ }, "node_modules/npm/node_modules/npm-audit-report": { "version": "6.0.0", + "dev": true, "inBundle": true, "license": "ISC", "engines": { @@ -6415,6 +6601,7 @@ }, "node_modules/npm/node_modules/npm-bundled": { "version": "4.0.0", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -6426,6 +6613,7 @@ }, "node_modules/npm/node_modules/npm-install-checks": { "version": "7.1.1", + "dev": true, "inBundle": true, "license": "BSD-2-Clause", "dependencies": { @@ -6437,6 +6625,7 @@ }, "node_modules/npm/node_modules/npm-normalize-package-bin": { "version": "4.0.0", + "dev": true, "inBundle": true, "license": "ISC", "engines": { @@ -6445,6 +6634,7 @@ }, "node_modules/npm/node_modules/npm-package-arg": { "version": "12.0.0", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -6459,6 +6649,7 @@ }, "node_modules/npm/node_modules/npm-packlist": { "version": "9.0.0", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -6470,6 +6661,7 @@ }, "node_modules/npm/node_modules/npm-pick-manifest": { "version": "10.0.0", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -6484,6 +6676,7 @@ }, "node_modules/npm/node_modules/npm-profile": { "version": "11.0.1", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -6496,6 +6689,7 @@ }, "node_modules/npm/node_modules/npm-registry-fetch": { "version": "18.0.2", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -6514,6 +6708,7 @@ }, "node_modules/npm/node_modules/npm-registry-fetch/node_modules/minizlib": { "version": "3.0.1", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -6526,6 +6721,7 @@ }, "node_modules/npm/node_modules/npm-user-validate": { "version": "3.0.0", + "dev": true, "inBundle": true, "license": "BSD-2-Clause", "engines": { @@ -6534,6 +6730,7 @@ }, "node_modules/npm/node_modules/p-map": { "version": "4.0.0", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -6548,11 +6745,13 @@ }, "node_modules/npm/node_modules/package-json-from-dist": { "version": "1.0.1", + "dev": true, "inBundle": true, "license": "BlueOak-1.0.0" }, "node_modules/npm/node_modules/pacote": { "version": "19.0.1", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -6583,6 +6782,7 @@ }, "node_modules/npm/node_modules/parse-conflict-json": { "version": "4.0.0", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -6596,6 +6796,7 @@ }, "node_modules/npm/node_modules/path-key": { "version": "3.1.1", + "dev": true, "inBundle": true, "license": "MIT", "engines": { @@ -6604,6 +6805,7 @@ }, "node_modules/npm/node_modules/path-scurry": { "version": "1.11.1", + "dev": true, "inBundle": true, "license": "BlueOak-1.0.0", "dependencies": { @@ -6619,6 +6821,7 @@ }, "node_modules/npm/node_modules/postcss-selector-parser": { "version": "6.1.2", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -6631,6 +6834,7 @@ }, "node_modules/npm/node_modules/proc-log": { "version": "5.0.0", + "dev": true, "inBundle": true, "license": "ISC", "engines": { @@ -6639,6 +6843,7 @@ }, "node_modules/npm/node_modules/proggy": { "version": "3.0.0", + "dev": true, "inBundle": true, "license": "ISC", "engines": { @@ -6647,6 +6852,7 @@ }, "node_modules/npm/node_modules/promise-all-reject-late": { "version": "1.0.1", + "dev": true, "inBundle": true, "license": "ISC", "funding": { @@ -6655,6 +6861,7 @@ }, "node_modules/npm/node_modules/promise-call-limit": { "version": "3.0.2", + "dev": true, "inBundle": true, "license": "ISC", "funding": { @@ -6663,11 +6870,13 @@ }, "node_modules/npm/node_modules/promise-inflight": { "version": "1.0.1", + "dev": true, "inBundle": true, "license": "ISC" }, "node_modules/npm/node_modules/promise-retry": { "version": "2.0.1", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -6680,6 +6889,7 @@ }, "node_modules/npm/node_modules/promzard": { "version": "2.0.0", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -6691,6 +6901,7 @@ }, "node_modules/npm/node_modules/qrcode-terminal": { "version": "0.12.0", + "dev": true, "inBundle": true, "bin": { "qrcode-terminal": "bin/qrcode-terminal.js" @@ -6698,6 +6909,7 @@ }, "node_modules/npm/node_modules/read": { "version": "4.0.0", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -6709,6 +6921,7 @@ }, "node_modules/npm/node_modules/read-cmd-shim": { "version": "5.0.0", + "dev": true, "inBundle": true, "license": "ISC", "engines": { @@ -6717,6 +6930,7 @@ }, "node_modules/npm/node_modules/read-package-json-fast": { "version": "4.0.0", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -6729,6 +6943,7 @@ }, "node_modules/npm/node_modules/retry": { "version": "0.12.0", + "dev": true, "inBundle": true, "license": "MIT", "engines": { @@ -6737,6 +6952,7 @@ }, "node_modules/npm/node_modules/rimraf": { "version": "5.0.10", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -6751,12 +6967,14 @@ }, "node_modules/npm/node_modules/safer-buffer": { "version": "2.1.2", + "dev": true, "inBundle": true, "license": "MIT", "optional": true }, "node_modules/npm/node_modules/semver": { "version": "7.6.3", + "dev": true, "inBundle": true, "license": "ISC", "bin": { @@ -6768,6 +6986,7 @@ }, "node_modules/npm/node_modules/shebang-command": { "version": "2.0.0", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -6779,6 +6998,7 @@ }, "node_modules/npm/node_modules/shebang-regex": { "version": "3.0.0", + "dev": true, "inBundle": true, "license": "MIT", "engines": { @@ -6787,6 +7007,7 @@ }, "node_modules/npm/node_modules/signal-exit": { "version": "4.1.0", + "dev": true, "inBundle": true, "license": "ISC", "engines": { @@ -6798,6 +7019,7 @@ }, "node_modules/npm/node_modules/sigstore": { "version": "3.0.0", + "dev": true, "inBundle": true, "license": "Apache-2.0", "dependencies": { @@ -6814,6 +7036,7 @@ }, "node_modules/npm/node_modules/sigstore/node_modules/@sigstore/bundle": { "version": "3.0.0", + "dev": true, "inBundle": true, "license": "Apache-2.0", "dependencies": { @@ -6825,6 +7048,7 @@ }, "node_modules/npm/node_modules/sigstore/node_modules/@sigstore/core": { "version": "2.0.0", + "dev": true, "inBundle": true, "license": "Apache-2.0", "engines": { @@ -6833,6 +7057,7 @@ }, "node_modules/npm/node_modules/sigstore/node_modules/@sigstore/sign": { "version": "3.0.0", + "dev": true, "inBundle": true, "license": "Apache-2.0", "dependencies": { @@ -6849,6 +7074,7 @@ }, "node_modules/npm/node_modules/sigstore/node_modules/@sigstore/verify": { "version": "2.0.0", + "dev": true, "inBundle": true, "license": "Apache-2.0", "dependencies": { @@ -6862,6 +7088,7 @@ }, "node_modules/npm/node_modules/smart-buffer": { "version": "4.2.0", + "dev": true, "inBundle": true, "license": "MIT", "engines": { @@ -6871,6 +7098,7 @@ }, "node_modules/npm/node_modules/socks": { "version": "2.8.3", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -6884,6 +7112,7 @@ }, "node_modules/npm/node_modules/socks-proxy-agent": { "version": "8.0.4", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -6897,6 +7126,7 @@ }, "node_modules/npm/node_modules/spdx-correct": { "version": "3.2.0", + "dev": true, "inBundle": true, "license": "Apache-2.0", "dependencies": { @@ -6906,6 +7136,7 @@ }, "node_modules/npm/node_modules/spdx-correct/node_modules/spdx-expression-parse": { "version": "3.0.1", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -6915,11 +7146,13 @@ }, "node_modules/npm/node_modules/spdx-exceptions": { "version": "2.5.0", + "dev": true, "inBundle": true, "license": "CC-BY-3.0" }, "node_modules/npm/node_modules/spdx-expression-parse": { "version": "4.0.0", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -6929,16 +7162,19 @@ }, "node_modules/npm/node_modules/spdx-license-ids": { "version": "3.0.20", + "dev": true, "inBundle": true, "license": "CC0-1.0" }, "node_modules/npm/node_modules/sprintf-js": { "version": "1.1.3", + "dev": true, "inBundle": true, "license": "BSD-3-Clause" }, "node_modules/npm/node_modules/ssri": { "version": "12.0.0", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -6950,6 +7186,7 @@ }, "node_modules/npm/node_modules/string-width": { "version": "4.2.3", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -6964,6 +7201,7 @@ "node_modules/npm/node_modules/string-width-cjs": { "name": "string-width", "version": "4.2.3", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -6977,6 +7215,7 @@ }, "node_modules/npm/node_modules/strip-ansi": { "version": "6.0.1", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -6989,6 +7228,7 @@ "node_modules/npm/node_modules/strip-ansi-cjs": { "name": "strip-ansi", "version": "6.0.1", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -7000,6 +7240,7 @@ }, "node_modules/npm/node_modules/supports-color": { "version": "9.4.0", + "dev": true, "inBundle": true, "license": "MIT", "engines": { @@ -7011,6 +7252,7 @@ }, "node_modules/npm/node_modules/tar": { "version": "6.2.1", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -7027,6 +7269,7 @@ }, "node_modules/npm/node_modules/tar/node_modules/fs-minipass": { "version": "2.1.0", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -7038,6 +7281,7 @@ }, "node_modules/npm/node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { "version": "3.3.6", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -7049,6 +7293,7 @@ }, "node_modules/npm/node_modules/tar/node_modules/minipass": { "version": "5.0.0", + "dev": true, "inBundle": true, "license": "ISC", "engines": { @@ -7057,16 +7302,19 @@ }, "node_modules/npm/node_modules/text-table": { "version": "0.2.0", + "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/tiny-relative-date": { "version": "1.3.0", + "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/treeverse": { "version": "3.0.0", + "dev": true, "inBundle": true, "license": "ISC", "engines": { @@ -7075,6 +7323,7 @@ }, "node_modules/npm/node_modules/tuf-js": { "version": "3.0.1", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -7088,6 +7337,7 @@ }, "node_modules/npm/node_modules/tuf-js/node_modules/@tufjs/models": { "version": "3.0.1", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -7100,6 +7350,7 @@ }, "node_modules/npm/node_modules/unique-filename": { "version": "4.0.0", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -7111,6 +7362,7 @@ }, "node_modules/npm/node_modules/unique-slug": { "version": "5.0.0", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -7122,11 +7374,13 @@ }, "node_modules/npm/node_modules/util-deprecate": { "version": "1.0.2", + "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/validate-npm-package-license": { "version": "3.0.4", + "dev": true, "inBundle": true, "license": "Apache-2.0", "dependencies": { @@ -7136,6 +7390,7 @@ }, "node_modules/npm/node_modules/validate-npm-package-license/node_modules/spdx-expression-parse": { "version": "3.0.1", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -7145,6 +7400,7 @@ }, "node_modules/npm/node_modules/validate-npm-package-name": { "version": "6.0.0", + "dev": true, "inBundle": true, "license": "ISC", "engines": { @@ -7153,11 +7409,13 @@ }, "node_modules/npm/node_modules/walk-up-path": { "version": "3.0.1", + "dev": true, "inBundle": true, "license": "ISC" }, "node_modules/npm/node_modules/which": { "version": "5.0.0", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -7172,6 +7430,7 @@ }, "node_modules/npm/node_modules/which/node_modules/isexe": { "version": "3.1.1", + "dev": true, "inBundle": true, "license": "ISC", "engines": { @@ -7180,6 +7439,7 @@ }, "node_modules/npm/node_modules/wrap-ansi": { "version": "8.1.0", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -7197,6 +7457,7 @@ "node_modules/npm/node_modules/wrap-ansi-cjs": { "name": "wrap-ansi", "version": "7.0.0", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -7213,6 +7474,7 @@ }, "node_modules/npm/node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { "version": "4.3.0", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -7227,6 +7489,7 @@ }, "node_modules/npm/node_modules/wrap-ansi/node_modules/ansi-regex": { "version": "6.1.0", + "dev": true, "inBundle": true, "license": "MIT", "engines": { @@ -7238,11 +7501,13 @@ }, "node_modules/npm/node_modules/wrap-ansi/node_modules/emoji-regex": { "version": "9.2.2", + "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/wrap-ansi/node_modules/string-width": { "version": "5.1.2", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -7259,6 +7524,7 @@ }, "node_modules/npm/node_modules/wrap-ansi/node_modules/strip-ansi": { "version": "7.1.0", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -7273,6 +7539,7 @@ }, "node_modules/npm/node_modules/write-file-atomic": { "version": "6.0.0", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -7285,6 +7552,7 @@ }, "node_modules/npm/node_modules/yallist": { "version": "4.0.0", + "dev": true, "inBundle": true, "license": "ISC" }, @@ -7310,6 +7578,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/on-exit-leak-free": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", + "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -7696,6 +7973,88 @@ "node": ">=4" } }, + "node_modules/pino": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-10.1.0.tgz", + "integrity": "sha512-0zZC2ygfdqvqK8zJIr1e+wT1T/L+LF6qvqvbzEQ6tiMAoTqEVK9a1K3YRu8HEUvGEvNqZyPJTtb2sNIoTkB83w==", + "license": "MIT", + "dependencies": { + "@pinojs/redact": "^0.4.0", + "atomic-sleep": "^1.0.0", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^2.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": "^3.0.0" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/pino-abstract-transport": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz", + "integrity": "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==", + "license": "MIT", + "dependencies": { + "split2": "^4.0.0" + } + }, + "node_modules/pino-pretty": { + "version": "13.1.3", + "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-13.1.3.tgz", + "integrity": "sha512-ttXRkkOz6WWC95KeY9+xxWL6AtImwbyMHrL1mSwqwW9u+vLp/WIElvHvCSDg0xO/Dzrggz1zv3rN5ovTRVowKg==", + "license": "MIT", + "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" + }, + "bin": { + "pino-pretty": "bin.js" + } + }, + "node_modules/pino-pretty/node_modules/pino-abstract-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-3.0.0.tgz", + "integrity": "sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg==", + "license": "MIT", + "dependencies": { + "split2": "^4.0.0" + } + }, + "node_modules/pino-pretty/node_modules/strip-json-comments": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-5.0.3.tgz", + "integrity": "sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw==", + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pino-std-serializers": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz", + "integrity": "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==", + "license": "MIT" + }, "node_modules/pkg-conf": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-2.1.0.tgz", @@ -7792,6 +8151,22 @@ "dev": true, "license": "MIT" }, + "node_modules/process-warning": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-5.0.0.tgz", + "integrity": "sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, "node_modules/proto-list": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", @@ -7843,6 +8218,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/quick-format-unescaped": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", + "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==", + "license": "MIT" + }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -7995,6 +8376,15 @@ "node": ">= 6" } }, + "node_modules/real-require": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", + "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", + "license": "MIT", + "engines": { + "node": ">= 12.13.0" + } + }, "node_modules/recast": { "version": "0.23.11", "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.11.tgz", @@ -8152,11 +8542,36 @@ } ] }, + "node_modules/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "node_modules/secure-json-parse": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-4.1.0.tgz", + "integrity": "sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/semantic-release": { "version": "24.2.1", "resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-24.2.1.tgz", @@ -8813,6 +9228,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/sonic-boom": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.0.tgz", + "integrity": "sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==", + "license": "MIT", + "dependencies": { + "atomic-sleep": "^1.0.0" + } + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -9155,6 +9579,15 @@ "node": ">=0.8" } }, + "node_modules/thread-stream": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz", + "integrity": "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==", + "license": "MIT", + "dependencies": { + "real-require": "^0.2.0" + } + }, "node_modules/through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", diff --git a/adminforth/package.json b/adminforth/package.json index 47749f829..2fbbf9ebe 100644 --- a/adminforth/package.json +++ b/adminforth/package.json @@ -82,6 +82,8 @@ "mysql2": "^3.14.2", "node-fetch": "^3.3.2", "pg": "^8.11.5", + "pino": "^10.1.0", + "pino-pretty": "^13.1.3", "rate-limiter-flexible": "^8.1.0", "recast": "^0.23.11", "ws": "^8.18.0" From cc90b21863de91ff239c1aa86f65287e91aa2843 Mon Sep 17 00:00:00 2001 From: yaroslav8765 Date: Fri, 9 Jan 2026 14:13:56 +0200 Subject: [PATCH 2/7] chore: update db logs to support pino logger --- adminforth/dataConnectors/mysql.ts | 27 +++++++++------------------ adminforth/dataConnectors/postgres.ts | 26 ++++++++------------------ adminforth/dataConnectors/sqlite.ts | 17 +++++------------ 3 files changed, 22 insertions(+), 48 deletions(-) diff --git a/adminforth/dataConnectors/mysql.ts b/adminforth/dataConnectors/mysql.ts index 2d2179c10..490c9c9d6 100644 --- a/adminforth/dataConnectors/mysql.ts +++ b/adminforth/dataConnectors/mysql.ts @@ -3,6 +3,7 @@ import { AdminForthResource, IAdminForthSingleFilter, IAdminForthAndOrFilter, IA import { AdminForthDataTypes, AdminForthFilterOperators, AdminForthSortDirections, } from '../types/Common.js'; import AdminForthBaseConnector from './baseConnector.js'; import mysql from 'mysql2/promise'; +import { dbLogger } from '../modules/logger.js'; class MysqlConnector extends AdminForthBaseConnector implements IAdminForthDataSourceConnector { @@ -317,9 +318,9 @@ class MysqlConnector extends AdminForthBaseConnector implements IAdminForthDataS if (orderBy) selectQuery += ` ${orderBy}`; if (limit) selectQuery += ` LIMIT ${limit}`; if (offset) selectQuery += ` OFFSET ${offset}`; - if (process.env.HEAVY_DEBUG_QUERY) { - console.log('šŸŖ²šŸ“œ MySQL Q:', selectQuery, 'values:', filterValues); - } + + dbLogger.trace(`šŸŖ²šŸ“œ MySQL Q: ${selectQuery} values: ${JSON.stringify(filterValues)}`); + const [results] = await this.client.execute(selectQuery, filterValues); return results.map((row) => { const newRow = {}; @@ -341,9 +342,7 @@ class MysqlConnector extends AdminForthBaseConnector implements IAdminForthDataS } const { sql: where, values: filterValues } = this.whereClauseAndValues(filters); const q = `SELECT COUNT(*) FROM ${tableName} ${where}`; - if (process.env.HEAVY_DEBUG_QUERY) { - console.log('šŸŖ²šŸ“œ MySQL Q:', q, 'values:', filterValues); - } + dbLogger.trace(`šŸŖ²šŸ“œ MySQL Q: ${q} values: ${JSON.stringify(filterValues)}`); const [results] = await this.client.execute(q, filterValues); return +results[0]["COUNT(*)"]; } @@ -353,9 +352,7 @@ class MysqlConnector extends AdminForthBaseConnector implements IAdminForthDataS const result = {}; await Promise.all(columns.map(async (col) => { const q = `SELECT MIN(${col.name}) as min, MAX(${col.name}) as max FROM ${tableName}`; - if (process.env.HEAVY_DEBUG_QUERY) { - console.log('šŸŖ²šŸ“œ MySQL Q:', q); - } + dbLogger.trace(`šŸŖ²šŸ“œ MySQL Q: ${q}`); const [results] = await this.client.execute(q); const { min, max } = results[0]; result[col.name] = { @@ -371,9 +368,7 @@ class MysqlConnector extends AdminForthBaseConnector implements IAdminForthDataS const placeholders = columns.map(() => '?').join(', '); const values = columns.map((colName) => typeof record[colName] === 'undefined' ? null : record[colName]); const q = `INSERT INTO ${tableName} (${columns.join(', ')}) VALUES (${placeholders})`; - if (process.env.HEAVY_DEBUG_QUERY) { - console.log('šŸŖ²šŸ“œ MySQL Q:', q, 'values:', values); - } + dbLogger.trace(`šŸŖ²šŸ“œ MySQL Q: ${q} values: ${JSON.stringify(values)}`); const ret = await this.client.execute(q, values); return ret.insertId; } @@ -382,17 +377,13 @@ class MysqlConnector extends AdminForthBaseConnector implements IAdminForthDataS const values = [...Object.values(newValues), recordId]; const columnsWithPlaceholders = Object.keys(newValues).map((col, i) => `${col} = ?`).join(', '); const q = `UPDATE ${resource.table} SET ${columnsWithPlaceholders} WHERE ${this.getPrimaryKey(resource)} = ?`; - if (process.env.HEAVY_DEBUG_QUERY) { - console.log('šŸŖ²šŸ“œ MySQL Q:', q, 'values:', values); - } + dbLogger.trace(`šŸŖ²šŸ“œ MySQL Q: ${q} values: ${JSON.stringify(values)}`); await this.client.execute(q, values); } async deleteRecord({ resource, recordId }): Promise { const q = `DELETE FROM ${resource.table} WHERE ${this.getPrimaryKey(resource)} = ?`; - if (process.env.HEAVY_DEBUG_QUERY) { - console.log('šŸŖ²šŸ“œ MySQL Q:', q, 'values:', [recordId]); - } + dbLogger.trace(`šŸŖ²šŸ“œ MySQL Q: ${q} values: ${JSON.stringify([recordId])}`); const res = await this.client.execute(q, [recordId]); return res.rowCount > 0; } diff --git a/adminforth/dataConnectors/postgres.ts b/adminforth/dataConnectors/postgres.ts index bae17dea8..b3e7fca77 100644 --- a/adminforth/dataConnectors/postgres.ts +++ b/adminforth/dataConnectors/postgres.ts @@ -3,6 +3,8 @@ import { AdminForthResource, IAdminForthSingleFilter, IAdminForthAndOrFilter, IA import { AdminForthDataTypes, AdminForthFilterOperators, AdminForthSortDirections, } from '../types/Common.js'; import AdminForthBaseConnector from './baseConnector.js'; import pkg from 'pg'; +import { dbLogger } from '../modules/logger.js'; + const { Client } = pkg; @@ -351,9 +353,7 @@ class PostgresConnector extends AdminForthBaseConnector implements IAdminForthDa const d = [...filterValues, limit, offset]; const orderBy = sort.length ? `ORDER BY ${sort.map((s) => `"${s.field}" ${this.SortDirectionsMap[s.direction]}`).join(', ')}` : ''; const selectQuery = `SELECT ${columns} FROM "${tableName}" ${where} ${orderBy} ${limitOffset}`; - if (process.env.HEAVY_DEBUG_QUERY) { - console.log('šŸŖ²šŸ“œ PG Q:', selectQuery, 'params:', d); - } + dbLogger.trace(`šŸŖ²šŸ“œ PG Q: ${selectQuery}, params: ${JSON.stringify(d)}`); const stmt = await this.client.query(selectQuery, d); const rows = stmt.rows; return rows.map((row) => { @@ -376,9 +376,7 @@ class PostgresConnector extends AdminForthBaseConnector implements IAdminForthDa } const { sql: where, values: filterValues } = this.whereClauseAndValues(resource, filters); const q = `SELECT COUNT(*) FROM "${tableName}" ${where}`; - if (process.env.HEAVY_DEBUG_QUERY) { - console.log('šŸŖ²šŸ“œ PG Q:', q, 'values:', filterValues); - } + dbLogger.trace(`šŸŖ²šŸ“œ PG Q: ${q}, values: ${JSON.stringify(filterValues)}`); const stmt = await this.client.query(q, filterValues); return +stmt.rows[0].count; } @@ -388,9 +386,7 @@ class PostgresConnector extends AdminForthBaseConnector implements IAdminForthDa const result = {}; await Promise.all(columns.map(async (col) => { const q = `SELECT MIN(${col.name}) as min, MAX(${col.name}) as max FROM "${tableName}"`; - if (process.env.HEAVY_DEBUG_QUERY) { - console.log('šŸŖ²šŸ“œ PG Q:', q); - } + dbLogger.trace(`šŸŖ²šŸ“œ PG Q: ${q}`); const stmt = await this.client.query(q); const { min, max } = stmt.rows[0]; result[col.name] = { @@ -412,9 +408,7 @@ class PostgresConnector extends AdminForthBaseConnector implements IAdminForthDa const q = `INSERT INTO "${tableName}" (${columns.join(', ')}) VALUES (${placeholders}) RETURNING "${primaryKey}"`; // console.log('\nšŸ”µ [PG INSERT]:', q); // console.log('šŸ“¦ [VALUES]:', JSON.stringify(values, null, 2)); - if (process.env.HEAVY_DEBUG_QUERY) { - console.log('šŸŖ²šŸ“œ PG Q:', q, 'values:', values); - } + dbLogger.trace(`šŸŖ²šŸ“œ PG Q: ${q}, values: ${JSON.stringify(values)}`); const ret = await this.client.query(q, values); return ret.rows[0][primaryKey]; } @@ -423,17 +417,13 @@ class PostgresConnector extends AdminForthBaseConnector implements IAdminForthDa const values = [...Object.values(newValues), recordId]; const columnsWithPlaceholders = Object.keys(newValues).map((col, i) => `"${col}" = $${i + 1}`).join(', '); const q = `UPDATE "${resource.table}" SET ${columnsWithPlaceholders} WHERE "${this.getPrimaryKey(resource)}" = $${values.length}`; - if (process.env.HEAVY_DEBUG_QUERY) { - console.log('šŸŖ²šŸ“œ PG Q:', q, 'values:', values); - } + dbLogger.trace(`šŸŖ²šŸ“œ PG Q: ${q}, values: ${JSON.stringify(values)}`); await this.client.query(q, values); } async deleteRecord({ resource, recordId }): Promise { const q = `DELETE FROM "${resource.table}" WHERE "${this.getPrimaryKey(resource)}" = $1`; - if (process.env.HEAVY_DEBUG_QUERY) { - console.log('šŸŖ²šŸ“œ PG Q:', q, 'values:', [recordId]); - } + dbLogger.trace(`šŸŖ²šŸ“œ PG Q: ${q}, values: ${JSON.stringify([recordId])}`); const res = await this.client.query(q, [recordId]); return res.rowCount > 0; } diff --git a/adminforth/dataConnectors/sqlite.ts b/adminforth/dataConnectors/sqlite.ts index 1b8b8f30e..2c4aa253c 100644 --- a/adminforth/dataConnectors/sqlite.ts +++ b/adminforth/dataConnectors/sqlite.ts @@ -3,6 +3,7 @@ import { IAdminForthDataSourceConnector, IAdminForthSingleFilter, IAdminForthAnd import AdminForthBaseConnector from './baseConnector.js'; import dayjs from 'dayjs'; import { AdminForthDataTypes, AdminForthFilterOperators, AdminForthSortDirections } from '../types/Common.js'; +import { dbLogger } from '../modules/logger.js'; class SQLiteConnector extends AdminForthBaseConnector implements IAdminForthDataSourceConnector { @@ -287,9 +288,7 @@ class SQLiteConnector extends AdminForthBaseConnector implements IAdminForthData const stmt = this.client.prepare(q); const d = [...filterValues, limit, offset]; - if (process.env.HEAVY_DEBUG_QUERY) { - console.log('šŸŖ²šŸ“œ SQLITE Q', q, 'params:', d); - } + dbLogger.trace(`šŸŖ²šŸ“œ SQLITE Q: ${q}, params: ${JSON.stringify(d)}`); const rows = await stmt.all(d); return rows.map((row) => { @@ -313,9 +312,7 @@ class SQLiteConnector extends AdminForthBaseConnector implements IAdminForthData const where = this.whereClause(filters); const filterValues = this.getFilterParams(filters); const q = `SELECT COUNT(*) FROM ${tableName} ${where}`; - if (process.env.HEAVY_DEBUG_QUERY) { - console.log('šŸŖ²šŸ“œ SQLITE Q', q, 'params:', filterValues); - } + dbLogger.trace(`šŸŖ²šŸ“œ SQLITE Q: ${q}, params: ${JSON.stringify(filterValues)}`); const totalStmt = this.client.prepare(q); return +totalStmt.get([...filterValues])['COUNT(*)']; } @@ -343,9 +340,7 @@ class SQLiteConnector extends AdminForthBaseConnector implements IAdminForthData //console.log('\n🟢 [SQLITE INSERT]:', sql); //console.log('šŸ“¦ [VALUES]:', JSON.stringify(values, null, 2)); const q = this.client.prepare(sql); - if (process.env.HEAVY_DEBUG_QUERY) { - console.log('šŸŖ²šŸ“œ SQL Q:', q, 'values:', values); - } + dbLogger.trace(`šŸŖ²šŸ“œ SQLITE Q: ${sql}, values: ${JSON.stringify(values)}`); const ret = await q.run(values); return ret.lastInsertRowid; } @@ -354,9 +349,7 @@ class SQLiteConnector extends AdminForthBaseConnector implements IAdminForthData const columnsWithPlaceholders = Object.keys(newValues).map((col) => `${col} = ?`); const values = [...Object.values(newValues), recordId]; const q = `UPDATE ${resource.table} SET ${columnsWithPlaceholders} WHERE ${this.getPrimaryKey(resource)} = ?`; - if (process.env.HEAVY_DEBUG_QUERY) { - console.log('šŸŖ²šŸ“œ SQLITE Q', q, 'params:', values); - } + dbLogger.trace(`šŸŖ²šŸ“œ SQLITE Q: ${q}, params: ${JSON.stringify(values)}`); const query = this.client.prepare(q); await query.run(values); } From 6b0d3bb438af67ab4efbf812ac573cf7a6e67855 Mon Sep 17 00:00:00 2001 From: yaroslav8765 Date: Fri, 9 Jan 2026 15:15:06 +0200 Subject: [PATCH 3/7] chore: use logge instead of HEAVY_DEBUG --- adminforth/basePlugin.ts | 6 +- adminforth/commands/callTsProxy.js | 11 +-- adminforth/commands/proxy.ts | 5 +- adminforth/dataConnectors/baseConnector.ts | 13 ++-- adminforth/index.ts | 81 +++++++++++----------- adminforth/modules/codeInjector.ts | 80 ++++++++++----------- adminforth/modules/logger.ts | 20 +++--- adminforth/modules/restApi.ts | 10 +-- adminforth/modules/socketBroker.ts | 8 +-- adminforth/servers/express.ts | 7 +- 10 files changed, 121 insertions(+), 120 deletions(-) diff --git a/adminforth/basePlugin.ts b/adminforth/basePlugin.ts index cbb3b37fa..82229b325 100644 --- a/adminforth/basePlugin.ts +++ b/adminforth/basePlugin.ts @@ -6,6 +6,8 @@ import fs from 'fs'; import crypto from 'crypto'; +import { afLogger } from './modules/logger.js'; + export default class AdminForthPlugin implements IAdminForthPlugin { @@ -24,7 +26,7 @@ export default class AdminForthPlugin implements IAdminForthPlugin { this.pluginDir = currentFileDir(metaUrl); this.customFolderPath = path.join(this.pluginDir, this.customFolderName); this.pluginOptions = pluginOptions; - process.env.HEAVY_DEBUG && console.log(`🪲 🪲 AdminForthPlugin.constructor`, this.constructor.name); + afLogger.trace(`🪲 🪲 AdminForthPlugin.constructor ${this.constructor.name}`); this.className = this.constructor.name; } @@ -42,7 +44,7 @@ export default class AdminForthPlugin implements IAdminForthPlugin { const seed = `af_pl_${this.constructor.name}_${resourceConfig.resourceId}_${uniqueness}`; this.pluginInstanceId = md5hash(seed); - process.env.HEAVY_DEBUG && console.log(`🪲 AdminForthPlugin.modifyResourceConfig`, seed, 'id', this.pluginInstanceId); + afLogger.trace(`🪲 AdminForthPlugin.modifyResourceConfig, ${seed}, 'id', ${this.pluginInstanceId}`); this.adminforth = adminforth; } diff --git a/adminforth/commands/callTsProxy.js b/adminforth/commands/callTsProxy.js index 55c37db09..737949025 100644 --- a/adminforth/commands/callTsProxy.js +++ b/adminforth/commands/callTsProxy.js @@ -4,6 +4,7 @@ import path from "path"; import fs from "fs"; import chalk from "chalk"; import dotenv from "dotenv"; +import { afLogger } from './modules/logger.js'; const currentFilePath = import.meta.url; const currentFileFolder = path.dirname(currentFilePath).replace("file:", ""); @@ -20,7 +21,7 @@ export function callTsProxy(tsCode, silent=false) { dotenv.config({ path: envPath, override: true }); } - process.env.HEAVY_DEBUG && console.log("🌐 Calling tsproxy with code:", path.join(currentFileFolder, "proxy.ts")); + afLogger.trace("🌐 Calling tsproxy with code:", path.join(currentFileFolder, "proxy.ts")); return new Promise((resolve, reject) => { const child = spawn("tsx", [path.join(currentFileFolder, "proxy.ts")], { env: process.env, @@ -59,14 +60,14 @@ export function callTsProxy(tsCode, silent=false) { } }); - process.env.HEAVY_DEBUG && console.log("🪲 Writing to tsproxy stdin...\n'''", tsCode, "'''"); + afLogger.trace("🪲 Writing to tsproxy stdin...\n'''", tsCode, "'''"); child.stdin.write(tsCode); child.stdin.end(); }); } export async function findAdminInstance() { - process.env.HEAVY_DEBUG && console.log("🌐 Finding admin instance..."); + afLogger.trace("🌐 Finding admin instance..."); const currentDirectory = process.cwd(); let files = fs.readdirSync(currentDirectory); @@ -83,7 +84,7 @@ export async function findAdminInstance() { for (const file of files) { if (file.endsWith(".ts")) { const fileNoTs = file.replace(/\.ts$/, ""); - process.env.HEAVY_DEBUG && console.log(`🪲 Trying bundleing ${file}...`); + afLogger.trace(`🪲 Trying bundleing ${file}...`); try { const res = await callTsProxy(` import { admin } from './${fileNoTs}.js'; @@ -104,7 +105,7 @@ export async function findAdminInstance() { console.error(chalk.red(`Error running ${file}:`, e)); process.exit(1); } - process.env.HEAVY_DEBUG && console.log(`🪲 File ${file} failed`, e); + afLogger.trace(`🪲 File ${file} failed`, e); } } } diff --git a/adminforth/commands/proxy.ts b/adminforth/commands/proxy.ts index c498326c9..3de2cec26 100644 --- a/adminforth/commands/proxy.ts +++ b/adminforth/commands/proxy.ts @@ -3,6 +3,7 @@ import { writeFile, unlink } from 'fs/promises'; import { randomUUID } from 'crypto'; import { pathToFileURL } from 'url'; import path from 'path'; +import { afLogger } from './modules/logger.js'; (async () => { const chunks: Buffer[] = []; @@ -23,8 +24,8 @@ import path from 'path'; capturedLogs.push(args); } - process.env.HEAVY_DEBUG && console.log(`🪲 TMP proxy file: ${tmpFile}`); - process.env.HEAVY_DEBUG && console.log(`🪲 Current working directory: ${process.cwd()}`); + afLogger.trace(`🪲 TMP proxy file: ${tmpFile}`); + afLogger.trace(`🪲 Current working directory: ${process.cwd()}`); try { // Save code to a temp file diff --git a/adminforth/dataConnectors/baseConnector.ts b/adminforth/dataConnectors/baseConnector.ts index eed448b8e..9d2d0953e 100644 --- a/adminforth/dataConnectors/baseConnector.ts +++ b/adminforth/dataConnectors/baseConnector.ts @@ -10,6 +10,7 @@ import { suggestIfTypo } from "../modules/utils.js"; import { AdminForthDataTypes, AdminForthFilterOperators, AdminForthSortDirections } from "../types/Common.js"; import { randomUUID } from "crypto"; import dayjs from "dayjs"; +import { afLogger } from '../modules/logger.js'; export default class AdminForthBaseConnector implements IAdminForthDataSourceConnectorBase { @@ -138,7 +139,7 @@ export default class AdminForthBaseConnector implements IAdminForthDataSourceCon ); } if (isPolymorphicTarget) { - process.env.HEAVY_DEBUG && console.log(`āš ļø Field '${filtersAsSingle.field}' not found in polymorphic target resource '${resource.resourceId}', allowing query to proceed.`); + afLogger.trace(`āš ļø Field '${filtersAsSingle.field}' not found in polymorphic target resource '${resource.resourceId}', allowing query to proceed.`); return { ok: true, error: '' }; } else { throw new Error(`Field '${filtersAsSingle.field}' not found in resource '${resource.resourceId}'. ${similar ? `Did you mean '${similar}'?` : ''}`); @@ -329,7 +330,7 @@ export default class AdminForthBaseConnector implements IAdminForthDataSourceCon } async checkUnique(resource: AdminForthResource, column: AdminForthResourceColumn, value: any, record?: any): Promise { - process.env.HEAVY_DEBUG && console.log('ā˜ļøšŸŖ²šŸŖ²šŸŖ²šŸŖ² checkUnique|||', column, value); + afLogger.trace('ā˜ļøšŸŖ²šŸŖ²šŸŖ²šŸŖ² checkUnique|||', column, value); const primaryKeyField = this.getPrimaryKey(resource); const existingRecord = await this.getData({ @@ -385,11 +386,11 @@ export default class AdminForthBaseConnector implements IAdminForthDataSourceCon }) ); if (error) { - process.env.HEAVY_DEBUG && console.log('šŸŖ²šŸ†• check unique error', error); + afLogger.trace('šŸŖ²šŸ†• check unique error', error); return { error, ok: false }; } - process.env.HEAVY_DEBUG && console.log('šŸŖ²šŸ†• creating record',JSON.stringify(recordWithOriginalValues)); + afLogger.trace('šŸŖ²šŸ†• creating record',JSON.stringify(recordWithOriginalValues)); let pkValue = await this.createRecordOriginalValues({ resource, record: recordWithOriginalValues }); if (recordWithOriginalValues[this.getPrimaryKey(resource)] !== undefined) { // some data sources always return some value for pk, even if it is was not auto generated @@ -441,12 +442,12 @@ export default class AdminForthBaseConnector implements IAdminForthDataSourceCon }) ); if (error) { - process.env.HEAVY_DEBUG && console.log('šŸŖ²šŸ†• check unique error', error); + afLogger.trace('šŸŖ²šŸ†• check unique error', error); return { error, ok: false }; } - process.env.HEAVY_DEBUG && console.log(`šŸŖ²āœļø updating record id:${recordId}, values: ${JSON.stringify(recordWithOriginalValues)}`); + afLogger.trace(`šŸŖ²āœļø updating record id:${recordId}, values: ${JSON.stringify(recordWithOriginalValues)}`); await this.updateRecordOriginalValues({ resource, recordId, newValues: recordWithOriginalValues }); diff --git a/adminforth/index.ts b/adminforth/index.ts index 25b48752c..de4f62361 100644 --- a/adminforth/index.ts +++ b/adminforth/index.ts @@ -34,6 +34,7 @@ import AdminForthRestAPI, { interpretResource } from './modules/restApi.js'; import ClickhouseConnector from './dataConnectors/clickhouse.js'; import OperationalResource from './modules/operationalResource.js'; import SocketBroker from './modules/socketBroker.js'; +import { afLogger } from './modules/logger.js'; // exports export * from './types/Back.js'; @@ -124,51 +125,51 @@ class AdminForth implements IAdminForth { } constructor(config: AdminForthInputConfig) { - process.env.HEAVY_DEBUG && console.log('šŸ”§ AdminForth constructor started'); + afLogger.trace('šŸ”§ AdminForth constructor started'); if (global.adminforth) { throw new Error('AdminForth instance already created in this process. '+ 'If you want to use multiple instances, consider using different process for each instance'); } - process.env.HEAVY_DEBUG && console.log('šŸ”§ Creating CodeInjector...'); + afLogger.trace('šŸ”§ Creating CodeInjector...'); this.codeInjector = new CodeInjector(this); - process.env.HEAVY_DEBUG && console.log('šŸ”§ CodeInjector created'); + afLogger.trace('šŸ”§ CodeInjector created'); - process.env.HEAVY_DEBUG && console.log('šŸ”§ Creating ConfigValidator...'); + afLogger.trace('šŸ”§ Creating ConfigValidator...'); this.configValidator = new ConfigValidator(this, config); - process.env.HEAVY_DEBUG && console.log('šŸ”§ ConfigValidator created'); + afLogger.trace('šŸ”§ ConfigValidator created'); - process.env.HEAVY_DEBUG && console.log('šŸ”§ Creating AdminForthRestAPI...'); + afLogger.trace('šŸ”§ Creating AdminForthRestAPI...'); this.restApi = new AdminForthRestAPI(this); - process.env.HEAVY_DEBUG && console.log('šŸ”§ AdminForthRestAPI created'); + afLogger.trace('šŸ”§ AdminForthRestAPI created'); - process.env.HEAVY_DEBUG && console.log('šŸ”§ Creating SocketBroker...'); + afLogger.trace('šŸ”§ Creating SocketBroker...'); this.websocket = new SocketBroker(this); - process.env.HEAVY_DEBUG && console.log('šŸ”§ SocketBroker created'); + afLogger.trace('šŸ”§ SocketBroker created'); this.activatedPlugins = []; - process.env.HEAVY_DEBUG && console.log('šŸ”§ Validating config...'); + afLogger.trace('šŸ”§ Validating config...'); this.configValidator.validateConfig(); - process.env.HEAVY_DEBUG && console.log('šŸ”§ Config validated'); + afLogger.trace('šŸ”§ Config validated'); - process.env.HEAVY_DEBUG && console.log('šŸ”§ Activating plugins...'); + afLogger.trace('šŸ”§ Activating plugins...'); this.activatePlugins(); - process.env.HEAVY_DEBUG && console.log('šŸ”§ Plugins activated'); + afLogger.trace('šŸ”§ Plugins activated'); - process.env.HEAVY_DEBUG && console.log('šŸ”§ Validating after plugin activation...'); + afLogger.trace('šŸ”§ Validating after plugin activation...'); this.configValidator.validateAfterPluginsActivation(); - process.env.HEAVY_DEBUG && console.log('šŸ”§ Config validated'); + afLogger.trace('šŸ”§ Config validated'); - process.env.HEAVY_DEBUG && console.log('šŸ”§ Creating ExpressServer...'); + afLogger.trace('šŸ”§ Creating ExpressServer...'); this.express = new ExpressServer(this); - process.env.HEAVY_DEBUG && console.log('šŸ”§ ExpressServer created'); + afLogger.trace('šŸ”§ ExpressServer created'); // this.fastify = new FastifyServer(this); - process.env.HEAVY_DEBUG && console.log('šŸ”§ Creating AdminForthAuth...'); + afLogger.trace('šŸ”§ Creating AdminForthAuth...'); this.auth = new AdminForthAuth(this); - process.env.HEAVY_DEBUG && console.log('šŸ”§ AdminForthAuth created'); + afLogger.trace('šŸ”§ AdminForthAuth created'); this.connectors = {}; this.statuses = { @@ -176,10 +177,10 @@ class AdminForth implements IAdminForth { }; console.log(`${this.formatAdminForth()} v${ADMINFORTH_VERSION} initializing...`); - process.env.HEAVY_DEBUG && console.log('šŸ”§ About to set global.adminforth...'); + afLogger.trace('šŸ”§ About to set global.adminforth...'); global.adminforth = this; - process.env.HEAVY_DEBUG && console.log('šŸ”§ global.adminforth set successfully'); - process.env.HEAVY_DEBUG && console.log('šŸ”§ AdminForth constructor completed'); + afLogger.trace('šŸ”§ global.adminforth set successfully'); + afLogger.trace('šŸ”§ AdminForth constructor completed'); } formatAdminForth() { @@ -202,16 +203,16 @@ class AdminForth implements IAdminForth { } activatePlugins() { - process.env.HEAVY_DEBUG && console.log('šŸ”ŒšŸ”ŒšŸ”Œ Activating plugins'); + afLogger.trace('šŸ”ŒšŸ”ŒšŸ”Œ Activating plugins'); const allPluginInstances = []; for (let resource of this.config.resources) { - process.env.HEAVY_DEBUG && console.log(`šŸ”Œ Checking plugins for resource: ${resource.resourceId}`); + afLogger.trace(`šŸ”Œ Checking plugins for resource: ${resource.resourceId}`); for (let pluginInstance of resource.plugins || []) { - process.env.HEAVY_DEBUG && console.log(`šŸ”Œ Found plugin: ${pluginInstance.constructor.name} for resource ${resource.resourceId}`); + afLogger.trace(`šŸ”Œ Found plugin: ${pluginInstance.constructor.name} for resource ${resource.resourceId}`); allPluginInstances.push({pi: pluginInstance, resource}); } } - process.env.HEAVY_DEBUG && console.log(`šŸ”Œ Total plugins to activate: ${allPluginInstances.length}`); + afLogger.trace(`šŸ”Œ Total plugins to activate: ${allPluginInstances.length}`); let activationLoopCounter = 0; while (true) { @@ -219,8 +220,8 @@ class AdminForth implements IAdminForth { if (activationLoopCounter > 10) { throw new Error('Plugin activation loop exceeded 10 iterations, possible infinite loop (some plugin tries to activate himself in a loop)'); } - process.env.HEAVY_DEBUG && console.log(`šŸ”Œ Plugin activation loop iteration: ${activationLoopCounter}`); - process.env.HEAVY_DEBUG && console.log(`šŸ”Œ Activated plugins count: ${this.activatedPlugins.length}/${allPluginInstances.length}`); + afLogger.trace(`šŸ”Œ Plugin activation loop iteration: ${activationLoopCounter}`); + afLogger.trace(`šŸ”Œ Activated plugins count: ${this.activatedPlugins.length}/${allPluginInstances.length}`); const allPluginsAreActivated = allPluginInstances.length === this.activatedPlugins.length; if (allPluginsAreActivated) { break; @@ -230,33 +231,33 @@ class AdminForth implements IAdminForth { !this.activatedPlugins.find((p) => p.pluginInstanceId === pluginInstance.pluginInstanceId) ); - process.env.HEAVY_DEBUG && console.log(`šŸ”Œ Unactivated plugins remaining: ${unactivatedPlugins.length}`); + afLogger.trace(`šŸ”Œ Unactivated plugins remaining: ${unactivatedPlugins.length}`); - process.env.HEAVY_DEBUG && console.log(`šŸ”Œ Unactivated plugins count: ${unactivatedPlugins.length}`); + afLogger.trace(`šŸ”Œ Unactivated plugins count: ${unactivatedPlugins.length}`); unactivatedPlugins.sort(({pi: a}, {pi: b}) => a.activationOrder - b.activationOrder); - process.env.HEAVY_DEBUG && console.log(`šŸ”Œ Activating plugins in order:`, unactivatedPlugins.map(({pi}) => pi.constructor.name)); + afLogger.trace(`šŸ”Œ Activating plugins in order: ${unactivatedPlugins.map(({pi}) => pi.constructor.name)}`); unactivatedPlugins.forEach( ({pi: pluginInstance, resource}, index) => { - process.env.HEAVY_DEBUG && console.log("Activating plugin:",pluginInstance.constructor.name) - process.env.HEAVY_DEBUG && console.log(`šŸ”Œ Activating plugin ${index + 1}/${allPluginInstances.length}: ${pluginInstance.constructor.name} for resource ${resource.resourceId}`); + afLogger.trace(`Activating plugin: ${pluginInstance.constructor.name}`); + afLogger.trace(`šŸ”Œ Activating plugin ${index + 1}/${allPluginInstances.length}: ${pluginInstance.constructor.name} for resource ${resource.resourceId}`); pluginInstance.modifyResourceConfig(this, resource, allPluginInstances); - process.env.HEAVY_DEBUG && console.log(`šŸ”Œ Plugin ${pluginInstance.constructor.name} modifyResourceConfig completed`); + afLogger.trace(`šŸ”Œ Plugin ${pluginInstance.constructor.name} modifyResourceConfig completed`); const plugin = this.activatedPlugins.find((p) => p.pluginInstanceId === pluginInstance.pluginInstanceId); if (plugin) { - process.env.HEAVY_DEBUG && console.log(`Current plugin pluginInstance.pluginInstanceId ${pluginInstance.pluginInstanceId}`); + afLogger.trace(`Current plugin pluginInstance.pluginInstanceId ${pluginInstance.pluginInstanceId}`); throw new Error(`Attempt to activate Plugin ${pluginInstance.constructor.name} second time for same resource, but plugin does not support it. To support multiple plugin instance pre one resource, plugin should return unique string values for each installation from instanceUniqueRepresentation`); } this.activatedPlugins.push(pluginInstance); - process.env.HEAVY_DEBUG && console.log(`šŸ”Œ Plugin ${pluginInstance.constructor.name} activated successfully`); + afLogger.trace(`šŸ”Œ Plugin ${pluginInstance.constructor.name} activated successfully`); } ); - process.env.HEAVY_DEBUG && console.log(`šŸ”Œactivated plugins:`, this.activatedPlugins.map((pi) => pi.constructor.name)); + afLogger.trace(`šŸ”Œactivated plugins: ${this.activatedPlugins.map((pi) => pi.constructor.name)}`); } - process.env.HEAVY_DEBUG && console.log('šŸ”Œ All plugins activation completed'); + afLogger.trace('šŸ”Œ All plugins activation completed'); } getPluginsByClassName(className: string): T[] { @@ -584,7 +585,7 @@ class AdminForth implements IAdminForth { } } const connector = this.connectors[resource.dataSource]; - process.env.HEAVY_DEBUG && console.log('šŸŖ²šŸ†• creating record createResourceRecord', record); + afLogger.trace(`šŸŖ²šŸ†• creating record createResourceRecord, record: ${JSON.stringify(record)}`); const { error, createdRecord } = await connector.createRecord({ resource, record, adminUser }); if ( error ) { return { error }; @@ -594,7 +595,7 @@ class AdminForth implements IAdminForth { // execute hook if needed for (const hook of listify(resource.hooks?.create?.afterSave)) { - process.env.HEAVY_DEBUG && console.log('🪲 Hook afterSave', hook); + afLogger.trace(`🪲 Hook afterSave ${hook}`); const resp = await hook({ recordId: primaryKey, resource, diff --git a/adminforth/modules/codeInjector.ts b/adminforth/modules/codeInjector.ts index 987c12ab8..a611ba3df 100644 --- a/adminforth/modules/codeInjector.ts +++ b/adminforth/modules/codeInjector.ts @@ -9,6 +9,7 @@ import AdminForth, { AdminForthConfigMenuItem } from '../index.js'; import { ADMIN_FORTH_ABSOLUTE_PATH, getComponentNameFromPath, transformObject, deepMerge, md5hash, slugifyString } from './utils.js'; import { ICodeInjector } from '../types/Back.js'; import { StylesGenerator } from './styleGenerator.js'; +import { afLogger } from '../modules/logger.js'; let TMP_DIR; @@ -131,9 +132,9 @@ class CodeInjector implements ICodeInjector { ...envOverrides, }; - console.log(`āš™ļø exec: npm ${command}`); - process.env.HEAVY_DEBUG && console.log(`🪲 npm ${command} cwd:`, cwd); - process.env.HEAVY_DEBUG && console.time(`npm ${command} done in`); + afLogger.trace(`āš™ļø exec: npm ${command}`); + afLogger.trace(`🪲 npm ${command} cwd:`, cwd); + afLogger.trace(`npm ${command} done in`); // On Windows, execute npm.cmd directly; on Unix, use node + npm let execCommand: string; @@ -159,11 +160,10 @@ class CodeInjector implements ICodeInjector { } const { stdout: out, stderr: err } = await execAsync(execCommand, execOptions); - process.env.HEAVY_DEBUG && console.timeEnd(`npm ${command} done in`); + afLogger.trace(`npm ${command} done in`); - // process.env.HEAVY_DEBUG && console.log(`🪲 npm ${command} output:`, out); if (err) { - process.env.HEAVY_DEBUG && console.error(`🪲npm ${command} errors/warnings:`, err); + afLogger.trace(`🪲npm ${command} errors/warnings:`, err); } } @@ -243,9 +243,7 @@ class CodeInjector implements ICodeInjector { dereference: true, // needed to dereference types // preserveTimestamps: true, // needed to not invalidate any caches }); - if (process.env.HEAVY_DEBUG) { - console.log('šŸŖ²āš™ļø fsExtra.copy copy single file', src, dest); - } + afLogger.trace('šŸŖ²āš™ļø fsExtra.copy copy single file', src, dest); })); } async migrateLegacyCustomLayout(oldMeta) { @@ -350,9 +348,7 @@ class CodeInjector implements ICodeInjector { registerSettingPages(this.adminforth.config.auth.userMenuSettingsPages); const spaDir = this.getSpaDir(); - if (process.env.HEAVY_DEBUG) { - console.log(`šŸŖ²āš™ļø fsExtra.copy from ${spaDir} -> ${this.spaTmpPath()}`); - } + afLogger.trace(`šŸŖ²āš™ļø fsExtra.copy from ${spaDir} -> ${this.spaTmpPath()}`); // try to rm /src/types directory try { @@ -368,8 +364,8 @@ class CodeInjector implements ICodeInjector { // /adminforth/* used for local development and /dist/* used for production const filterPasses = !src.includes(`${path.sep}adminforth${path.sep}spa${path.sep}node_modules`) && !src.includes(`${path.sep}adminforth${path.sep}spa${path.sep}dist`) && !src.includes(`${path.sep}dist${path.sep}spa${path.sep}node_modules`) && !src.includes(`${path.sep}dist${path.sep}spa${path.sep}dist`); - if (process.env.HEAVY_DEBUG && !filterPasses) { - console.log('šŸŖ²āš™ļø fsExtra.copy filtered out', src); + if (!filterPasses) { + afLogger.trace('šŸŖ²āš™ļø fsExtra.copy filtered out', src); } return filterPasses @@ -398,9 +394,7 @@ class CodeInjector implements ICodeInjector { for (const [src, dest] of Object.entries(this.srcFoldersToSync)) { const to = path.join(this.spaTmpPath(), 'src', 'custom', dest); - if (process.env.HEAVY_DEBUG) { - console.log(`šŸŖ²āš™ļø srcFoldersToSync: fsExtra.copy from ${src}, ${to}`); - } + afLogger.trace(`šŸŖ²āš™ļø srcFoldersToSync: fsExtra.copy from ${src}, ${to}`); await fsExtra.copy(src, to, { recursive: true, @@ -649,7 +643,7 @@ class CodeInjector implements ICodeInjector { // for every installed plugin generate packages for (const plugin of this.adminforth.activatedPlugins) { - process.env.HEAVY_DEBUG && console.log('šŸ”§ Checking packages for plugin', plugin.constructor.name, plugin.customFolderPath); + afLogger.trace('šŸ”§ Checking packages for plugin', plugin.constructor.name, plugin.customFolderPath); const [lockHash, packages] = await this.packagesFromNpm(plugin.customFolderPath); if (packages.length) { pluginPackages.push({ @@ -670,14 +664,14 @@ class CodeInjector implements ICodeInjector { try { const existingHash = await fs.promises.readFile(hashPath, 'utf-8'); if (existingHash === fullHash) { - process.env.HEAVY_DEBUG && console.log(`🪲Hashes match, skipping npm ci/install, from file: ${existingHash}, actual: ${fullHash}`); + afLogger.trace(`🪲Hashes match, skipping npm ci/install, from file: ${existingHash}, actual: ${fullHash}`); return; } else { - process.env.HEAVY_DEBUG && console.log(`🪲 Hashes do not match: from file: ${existingHash} actual: ${fullHash}, proceeding with npm ci/install`); + afLogger.trace(`🪲 Hashes do not match: from file: ${existingHash} actual: ${fullHash}, proceeding with npm ci/install`); } } catch (e) { // ignore - process.env.HEAVY_DEBUG && console.log('🪲Hash file does not exist, proceeding with npm ci/install', e); + afLogger.trace('🪲Hash file does not exist, proceeding with npm ci/install', e); } await this.runNpmShell({command: 'ci', cwd: this.spaTmpPath(), envOverrides: { @@ -730,7 +724,7 @@ class CodeInjector implements ICodeInjector { }; await collectDirectories(spaPath); - process.env.HEAVY_DEBUG && console.log('šŸŖ²šŸ”Ž Watch for:', directories.join(',')); + afLogger.trace('šŸŖ²šŸ”Ž Watch for:', directories.join(',')); const watcher = filewatcher({ debounce: 30 }); directories.forEach((dir) => { @@ -739,7 +733,7 @@ class CodeInjector implements ICodeInjector { files.forEach((file) => { const fullPath = path.join(dir, file); if (fs.lstatSync(fullPath).isFile()) { - process.env.HEAVY_DEBUG && console.log(`šŸŖ²šŸ”Ž Watch for file ${fullPath}`); + afLogger.trace(`šŸŖ²šŸ”Ž Watch for file ${fullPath}`); watcher.add(fullPath); } }) @@ -748,7 +742,7 @@ class CodeInjector implements ICodeInjector { watcher.on( 'change', async (file) => { - process.env.HEAVY_DEBUG && console.log(`šŸ› File ${file} changed (SPA), preparing sources...`); + afLogger.trace(`šŸ› File ${file} changed (SPA), preparing sources...`); await this.updatePartials({ filesUpdated: [file.replace(spaPath + path.sep, '')] }); } ) @@ -764,7 +758,7 @@ class CodeInjector implements ICodeInjector { try { await fs.promises.access(customComponentsDir, fs.constants.F_OK); } catch (e) { - process.env.HEAVY_DEBUG && console.log(`🪲Custom components dir ${customComponentsDir} does not exist, skipping watching`); + afLogger.trace(`🪲Custom components dir ${customComponentsDir} does not exist, skipping watching`); return; } @@ -796,27 +790,25 @@ class CodeInjector implements ICodeInjector { const watcher = filewatcher({ debounce: 30 }); files.forEach((file) => { - process.env.HEAVY_DEBUG && console.log(`šŸŖ²šŸ”Ž Watch for file ${file}`); + afLogger.trace(`šŸŖ²šŸ”Ž Watch for file ${file}`); watcher.add(file); }); - process.env.HEAVY_DEBUG && console.log('šŸŖ²šŸ”Ž Watch for:', directories.join(',')); + afLogger.trace('šŸŖ²šŸ”Ž Watch for:', directories.join(',')); watcher.on( 'change', async (fileOrDir) => { // copy one file const relativeFilename = fileOrDir.replace(customComponentsDir + path.sep, ''); - if (process.env.HEAVY_DEBUG) { - console.log(`šŸ”Ž fileOrDir ${fileOrDir} changed`); - console.log(`šŸ”Ž relativeFilename ${relativeFilename}`); - console.log(`šŸ”Ž customComponentsDir ${customComponentsDir}`); - console.log(`šŸ”Ž destination ${destination}`); - } + afLogger.trace(`šŸ”Ž fileOrDir ${fileOrDir} changed`); + afLogger.trace(`šŸ”Ž relativeFilename ${relativeFilename}`); + afLogger.trace(`šŸ”Ž customComponentsDir ${customComponentsDir}`); + afLogger.trace(`šŸ”Ž destination ${destination}`); const isFile = fs.lstatSync(fileOrDir).isFile(); if (isFile) { const destPath = path.join(this.spaTmpPath(), 'src', 'custom', destination, relativeFilename); - process.env.HEAVY_DEBUG && console.log(`šŸ”Ž Copying file ${fileOrDir} to ${destPath}`); + afLogger.trace(`šŸ”Ž Copying file ${fileOrDir} to ${destPath}`); await fsExtra.copy(fileOrDir, destPath); return; } else { @@ -836,7 +828,7 @@ class CodeInjector implements ICodeInjector { return content; } catch (e) { // file does not exist - process.env.HEAVY_DEBUG && console.log(`🪲File ${filePath} does not exist, returning null`); + afLogger.trace(`🪲File ${filePath} does not exist, returning null`); return null; } } @@ -890,7 +882,7 @@ class CodeInjector implements ICodeInjector { const allFiles = []; const sourcesHash = await this.computeSourcesHash(this.spaTmpPath(), allFiles); - process.env.VERY_HEAVY_DEBUG && console.log('🪲🪲 allFiles:', JSON.stringify( + afLogger.trace('🪲🪲 allFiles:', JSON.stringify( allFiles.sort((a,b) => a.localeCompare(b)), null, 1)) const buildHash = await this.tryReadFile(path.join(serveDir, '.adminforth_build_hash')); @@ -899,11 +891,9 @@ class CodeInjector implements ICodeInjector { const skipBuild = buildHash === sourcesHash; const skipExtract = messagesHash === sourcesHash; - if (process.env.HEAVY_DEBUG) { - console.log(`🪲 SPA build hash: ${buildHash}`); - console.log(`🪲 SPA messages hash: ${messagesHash}`); - console.log(`🪲 SPA sources hash: ${sourcesHash}`); - } + afLogger.trace(`🪲 SPA build hash: ${buildHash}`); + afLogger.trace(`🪲 SPA messages hash: ${messagesHash}`); + afLogger.trace(`🪲 SPA sources hash: ${sourcesHash}`); if (!skipBuild) { // remove serveDir if exists @@ -973,19 +963,19 @@ class CodeInjector implements ICodeInjector { // parse port from message " āžœ Local: http://localhost:xyz/" const s = stripAnsiCodes(data.toString()); - process.env.HEAVY_DEBUG && console.log('🪲 devServer stdout āžœ (port detect):', s); + afLogger.trace('🪲 devServer stdout āžœ (port detect):', s); const portMatch = s.match(/.+?http:\/\/.+?:(\d+).+?/m); if (portMatch) { this.devServerPort = parseInt(portMatch[1]); } } else { - process.env.HEAVY_DEBUG && console.log(`[AdminForth SPA]:`); - process.env.HEAVY_DEBUG && process.stdout.write(data); + afLogger.trace(`[AdminForth SPA]:`); + afLogger.trace(data.toString()); } }); devServer.stderr.on('data', (data) => { console.error(`[AdminForth SPA ERROR]:`); - process.stdout.write(data); + afLogger.trace(data.toString()); }); } diff --git a/adminforth/modules/logger.ts b/adminforth/modules/logger.ts index 6e89ee183..06f3a8ece 100644 --- a/adminforth/modules/logger.ts +++ b/adminforth/modules/logger.ts @@ -1,25 +1,29 @@ import pino from 'pino'; import { PinoPretty } from "pino-pretty"; -export const logger = pino({ +const baseLogger = pino({ transport: { target: 'pino-pretty', options: { colorize: true, ignore: 'pid,hostname', hideObject: true, - messageFormat: '[{level}] ({layer}) {msg}', + messageFormat: '{layer}: {msg}', } }, - level: process.env.HEAVY_DEBUG ? 'trace' : ( process.env.DEBUG_LEVEL || 'info' ) }); -export const afLogger = logger.child( - { layer: 'adminforth' }, - { level: process.env.HEAVY_DEBUG ? 'trace' : ( process.env.DEBUG_LEVEL || 'info' ) } +export const logger = baseLogger.child( + { layer: 'user_logs' }, + { level: process.env.HEAVY_DEBUG ? 'trace' : ( process.env.DEBUG_LEVEL || 'info' ) } ); -export const dbLogger = logger.child( +export const afLogger = baseLogger.child( + { layer: 'af' }, + { level: process.env.HEAVY_DEBUG ? 'trace' : ( process.env.AF_DEBUG_LEVEL || 'info' ) } +); + +export const dbLogger = baseLogger.child( { layer: 'db' }, - { level: process.env.HEAVY_DEBUG_QUERY ? 'trace' : (process.env.DEBUG_LEVEL_DB_QUERY || 'info') } + { level: process.env.HEAVY_DEBUG_QUERY ? 'trace' : (process.env.DB_DEBUG_LEVEL|| 'info') } ); \ No newline at end of file diff --git a/adminforth/modules/restApi.ts b/adminforth/modules/restApi.ts index 1f784d3fe..07e7bb921 100644 --- a/adminforth/modules/restApi.ts +++ b/adminforth/modules/restApi.ts @@ -15,6 +15,8 @@ import { Filters, } from "../types/Back.js"; +import { logger, afLogger, dbLogger } from "./logger.js"; + import { ADMINFORTH_VERSION, listify, md5hash, getLoginPromptHTML } from './utils.js'; import AdminForthAuth from "../auth.js"; @@ -77,9 +79,7 @@ export async function interpretResource( source: ActionCheckSource, adminforth: IAdminForth ): Promise<{allowedActions: AllowedActionsResolved}> { - if (process.env.HEAVY_DEBUG) { - console.log('🪲Interpreting resource', resource.resourceId, source, 'adminUser', adminUser); - } + afLogger.trace(`🪲Interpreting resource, ${resource.resourceId}, ${source}, 'adminUser', ${adminUser}`); const allowedActions = {} as AllowedActionsResolved; // we need to compute only allowed actions for this source: @@ -1046,13 +1046,13 @@ export default class AdminForthRestAPI implements IAdminForthRestAPI { const availableSearchFields = searchableFields.filter((fieldName) => { const fieldExists = targetResource.columns.some(col => col.name === fieldName); if (!fieldExists) { - process.env.HEAVY_DEBUG && console.log(`āš ļø Field '${fieldName}' not found in polymorphic target resource '${targetResource.resourceId}', skipping in search filter.`); + afLogger.trace(`āš ļø Field '${fieldName}' not found in polymorphic target resource '${targetResource.resourceId}', skipping in search filter.`); } return fieldExists; }); if (availableSearchFields.length === 0) { - process.env.HEAVY_DEBUG && console.log(`āš ļø No searchable fields available in polymorphic target resource '${targetResource.resourceId}', skipping resource.`); + afLogger.trace(`āš ļø No searchable fields available in polymorphic target resource '${targetResource.resourceId}', skipping resource.`); resolve({ items: [] }); return; } diff --git a/adminforth/modules/socketBroker.ts b/adminforth/modules/socketBroker.ts index 6fe9e9880..a4db7606e 100644 --- a/adminforth/modules/socketBroker.ts +++ b/adminforth/modules/socketBroker.ts @@ -1,5 +1,6 @@ import { IAdminForth, IWebSocketBroker, IWebSocketClient } from "../types/Back.js"; import { AdminUser } from "../types/Common.js"; +import { afLogger } from '../modules/logger.js'; export default class SocketBroker implements IWebSocketBroker { clients: IWebSocketClient[] = []; @@ -125,18 +126,17 @@ export default class SocketBroker implements IWebSocketBroker { async publish(topic: string, data: any, filterUsers?: (adminUser: AdminUser) => Promise): Promise { if (!this.topics[topic]) { - process.env.HEAVY_DEBUG && console.log('No clients subscribed to topic', topic); + afLogger.trace('No clients subscribed to topic', topic); return; } for (const client of this.topics[topic]) { if (filterUsers) { if (! (await filterUsers(client.adminUser)) ) { - process.env.HEAVY_DEBUG && console.log('Client not authorized to receive message', topic, client.adminUser); + afLogger.trace('Client not authorized to receive message', topic, client.adminUser); continue; } } - process.env.HEAVY_DEBUG && console.log('Sending data to soket', topic, data); - + afLogger.trace('Sending data to socket', topic, data); client.send(JSON.stringify({ type: 'message', topic, data })); } } diff --git a/adminforth/servers/express.ts b/adminforth/servers/express.ts index b732ceb67..d86b8181e 100644 --- a/adminforth/servers/express.ts +++ b/adminforth/servers/express.ts @@ -10,6 +10,7 @@ import { AdminUser } from '../types/Common.js'; import http from 'http'; import { randomUUID } from 'crypto'; import { listify } from '../modules/utils.js'; +import { afLogger } from '../modules/logger.js'; function replaceAtStart(string, substring) { if (string.startsWith(substring)) { @@ -119,7 +120,7 @@ class ExpressServer implements IExpressHttpServer { } } this.expressApp.get(`${slashedPrefix}assets/*`, handler); - process.env.HEAVY_DEBUG && console.log('Ā®ļø Registering SPA serve handler', `${slashedPrefix}assets/*`); + afLogger.trace(`Ā®ļø Registering SPA serve handler', ${slashedPrefix}assets/*`); this.expressApp.get(`${prefix}*`, handler); @@ -330,7 +331,7 @@ class ExpressServer implements IExpressHttpServer { message: undefined, setHeader(name, value) { - process.env.HEAVY_DEBUG && console.log(' 🪲Setting header', name, value); + afLogger.trace(`🪲Setting header, ${name}, ${value}`); this.headers.push([name, value]); }, @@ -376,7 +377,7 @@ class ExpressServer implements IExpressHttpServer { res.json(output); } - process.env.HEAVY_DEBUG && console.log(`šŸ‘‚ Adding endpoint ${method} ${fullPath}`); + afLogger.trace(`šŸ‘‚ Adding endpoint ${method} ${fullPath}`); this.expressApp[method.toLowerCase()](fullPath, noAuth ? expressHandler : this.authorize(expressHandler)); } From b7b70f6d46d69889bafa354716159cb307449540 Mon Sep 17 00:00:00 2001 From: yaroslav8765 Date: Fri, 9 Jan 2026 15:21:30 +0200 Subject: [PATCH 4/7] chore: enhance logging messages for clarity in baseConnector, codeInjector, and socketBroker modules --- adminforth/dataConnectors/baseConnector.ts | 8 ++++---- adminforth/modules/codeInjector.ts | 22 +++++++++++----------- adminforth/modules/socketBroker.ts | 6 +++--- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/adminforth/dataConnectors/baseConnector.ts b/adminforth/dataConnectors/baseConnector.ts index 9d2d0953e..234d8d641 100644 --- a/adminforth/dataConnectors/baseConnector.ts +++ b/adminforth/dataConnectors/baseConnector.ts @@ -330,7 +330,7 @@ export default class AdminForthBaseConnector implements IAdminForthDataSourceCon } async checkUnique(resource: AdminForthResource, column: AdminForthResourceColumn, value: any, record?: any): Promise { - afLogger.trace('ā˜ļøšŸŖ²šŸŖ²šŸŖ²šŸŖ² checkUnique|||', column, value); + afLogger.trace(`ā˜ļøšŸŖ²šŸŖ²šŸŖ²šŸŖ² checkUnique||| ${column.name}, ${value}`); const primaryKeyField = this.getPrimaryKey(resource); const existingRecord = await this.getData({ @@ -386,11 +386,11 @@ export default class AdminForthBaseConnector implements IAdminForthDataSourceCon }) ); if (error) { - afLogger.trace('šŸŖ²šŸ†• check unique error', error); + afLogger.trace(`šŸŖ²šŸ†• check unique error, ${error}`); return { error, ok: false }; } - afLogger.trace('šŸŖ²šŸ†• creating record',JSON.stringify(recordWithOriginalValues)); + afLogger.trace(`šŸŖ²šŸ†• creating record, ${JSON.stringify(recordWithOriginalValues)}`); let pkValue = await this.createRecordOriginalValues({ resource, record: recordWithOriginalValues }); if (recordWithOriginalValues[this.getPrimaryKey(resource)] !== undefined) { // some data sources always return some value for pk, even if it is was not auto generated @@ -442,7 +442,7 @@ export default class AdminForthBaseConnector implements IAdminForthDataSourceCon }) ); if (error) { - afLogger.trace('šŸŖ²šŸ†• check unique error', error); + afLogger.trace(`šŸŖ²šŸ†• check unique error, ${error}`); return { error, ok: false }; } diff --git a/adminforth/modules/codeInjector.ts b/adminforth/modules/codeInjector.ts index a611ba3df..fb0d526b9 100644 --- a/adminforth/modules/codeInjector.ts +++ b/adminforth/modules/codeInjector.ts @@ -133,7 +133,7 @@ class CodeInjector implements ICodeInjector { }; afLogger.trace(`āš™ļø exec: npm ${command}`); - afLogger.trace(`🪲 npm ${command} cwd:`, cwd); + afLogger.trace(`🪲 npm ${command} cwd: ${cwd}`); afLogger.trace(`npm ${command} done in`); // On Windows, execute npm.cmd directly; on Unix, use node + npm @@ -163,7 +163,7 @@ class CodeInjector implements ICodeInjector { afLogger.trace(`npm ${command} done in`); if (err) { - afLogger.trace(`🪲npm ${command} errors/warnings:`, err); + afLogger.trace(`🪲npm ${command} errors/warnings: ${err}`); } } @@ -243,7 +243,7 @@ class CodeInjector implements ICodeInjector { dereference: true, // needed to dereference types // preserveTimestamps: true, // needed to not invalidate any caches }); - afLogger.trace('šŸŖ²āš™ļø fsExtra.copy copy single file', src, dest); + afLogger.trace(`šŸŖ²āš™ļø fsExtra.copy copy single file, ${src}, ${dest}`); })); } async migrateLegacyCustomLayout(oldMeta) { @@ -365,7 +365,7 @@ class CodeInjector implements ICodeInjector { const filterPasses = !src.includes(`${path.sep}adminforth${path.sep}spa${path.sep}node_modules`) && !src.includes(`${path.sep}adminforth${path.sep}spa${path.sep}dist`) && !src.includes(`${path.sep}dist${path.sep}spa${path.sep}node_modules`) && !src.includes(`${path.sep}dist${path.sep}spa${path.sep}dist`); if (!filterPasses) { - afLogger.trace('šŸŖ²āš™ļø fsExtra.copy filtered out', src); + afLogger.trace(`šŸŖ²āš™ļø fsExtra.copy filtered out, ${src}`); } return filterPasses @@ -643,7 +643,7 @@ class CodeInjector implements ICodeInjector { // for every installed plugin generate packages for (const plugin of this.adminforth.activatedPlugins) { - afLogger.trace('šŸ”§ Checking packages for plugin', plugin.constructor.name, plugin.customFolderPath); + afLogger.trace(`šŸ”§ Checking packages for plugin, ${plugin.constructor.name}, ${plugin.customFolderPath}`); const [lockHash, packages] = await this.packagesFromNpm(plugin.customFolderPath); if (packages.length) { pluginPackages.push({ @@ -671,7 +671,7 @@ class CodeInjector implements ICodeInjector { } } catch (e) { // ignore - afLogger.trace('🪲Hash file does not exist, proceeding with npm ci/install', e); + afLogger.trace(`🪲Hash file does not exist, proceeding with npm ci/install, ${e}`); } await this.runNpmShell({command: 'ci', cwd: this.spaTmpPath(), envOverrides: { @@ -724,7 +724,7 @@ class CodeInjector implements ICodeInjector { }; await collectDirectories(spaPath); - afLogger.trace('šŸŖ²šŸ”Ž Watch for:', directories.join(',')); + afLogger.trace(`šŸŖ²šŸ”Ž Watch for: ${directories.join(',')}`); const watcher = filewatcher({ debounce: 30 }); directories.forEach((dir) => { @@ -794,7 +794,7 @@ class CodeInjector implements ICodeInjector { watcher.add(file); }); - afLogger.trace('šŸŖ²šŸ”Ž Watch for:', directories.join(',')); + afLogger.trace(`šŸŖ²šŸ”Ž Watch for: ${directories.join(',')}`); watcher.on( 'change', @@ -882,8 +882,8 @@ class CodeInjector implements ICodeInjector { const allFiles = []; const sourcesHash = await this.computeSourcesHash(this.spaTmpPath(), allFiles); - afLogger.trace('🪲🪲 allFiles:', JSON.stringify( - allFiles.sort((a,b) => a.localeCompare(b)), null, 1)) + afLogger.trace(`🪲🪲 allFiles:, ${JSON.stringify( + allFiles.sort((a,b) => a.localeCompare(b)), null, 1)}`); const buildHash = await this.tryReadFile(path.join(serveDir, '.adminforth_build_hash')); const messagesHash = await this.tryReadFile(path.join(serveDir, '.adminforth_messages_hash')); @@ -963,7 +963,7 @@ class CodeInjector implements ICodeInjector { // parse port from message " āžœ Local: http://localhost:xyz/" const s = stripAnsiCodes(data.toString()); - afLogger.trace('🪲 devServer stdout āžœ (port detect):', s); + afLogger.trace(`🪲 devServer stdout āžœ (port detect): ${s}`); const portMatch = s.match(/.+?http:\/\/.+?:(\d+).+?/m); if (portMatch) { this.devServerPort = parseInt(portMatch[1]); diff --git a/adminforth/modules/socketBroker.ts b/adminforth/modules/socketBroker.ts index a4db7606e..758168129 100644 --- a/adminforth/modules/socketBroker.ts +++ b/adminforth/modules/socketBroker.ts @@ -126,17 +126,17 @@ export default class SocketBroker implements IWebSocketBroker { async publish(topic: string, data: any, filterUsers?: (adminUser: AdminUser) => Promise): Promise { if (!this.topics[topic]) { - afLogger.trace('No clients subscribed to topic', topic); + afLogger.trace(`No clients subscribed to topic ${topic}`); return; } for (const client of this.topics[topic]) { if (filterUsers) { if (! (await filterUsers(client.adminUser)) ) { - afLogger.trace('Client not authorized to receive message', topic, client.adminUser); + afLogger.trace(`Client not authorized to receive message ${topic} ${client.adminUser}`); continue; } } - afLogger.trace('Sending data to socket', topic, data); + afLogger.trace(`Sending data to socket ${topic} ${JSON.stringify(data)}`); client.send(JSON.stringify({ type: 'message', topic, data })); } } From 9541c4d005da5d669f26cd99a3fd189cf74b1d9b Mon Sep 17 00:00:00 2001 From: yaroslav8765 Date: Fri, 9 Jan 2026 15:23:32 +0200 Subject: [PATCH 5/7] fix: correct import path for afLogger in proxy.ts --- adminforth/commands/proxy.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adminforth/commands/proxy.ts b/adminforth/commands/proxy.ts index 3de2cec26..61ddb6ebf 100644 --- a/adminforth/commands/proxy.ts +++ b/adminforth/commands/proxy.ts @@ -3,7 +3,7 @@ import { writeFile, unlink } from 'fs/promises'; import { randomUUID } from 'crypto'; import { pathToFileURL } from 'url'; import path from 'path'; -import { afLogger } from './modules/logger.js'; +import { afLogger } from '../modules/logger.js'; (async () => { const chunks: Buffer[] = []; From 7b1718bdeb37af803cead0c1642d7b37e598b15d Mon Sep 17 00:00:00 2001 From: yaroslav8765 Date: Fri, 9 Jan 2026 15:51:26 +0200 Subject: [PATCH 6/7] chore: replace console logging with afLogger for consistent logging across components --- adminforth/commands/bundle.js | 5 +- adminforth/commands/callTsProxy.js | 4 +- adminforth/commands/createApp/utils.js | 8 +- .../createCustomComponent/configLoader.js | 7 +- .../createCustomComponent/configUpdater.js | 85 ++++++++++--------- .../createCustomComponent/fileGenerator.js | 29 ++++--- .../commands/createCustomComponent/main.js | 3 +- adminforth/commands/postinstall.js | 10 ++- adminforth/commands/utils.js | 5 +- adminforth/dataConnectors/baseConnector.ts | 1 - adminforth/dataConnectors/mongo.ts | 8 +- adminforth/dataConnectors/postgres.ts | 6 +- adminforth/dataConnectors/sqlite.ts | 3 - adminforth/index.ts | 7 +- 14 files changed, 90 insertions(+), 91 deletions(-) diff --git a/adminforth/commands/bundle.js b/adminforth/commands/bundle.js index 42b882bef..9bb4d622b 100644 --- a/adminforth/commands/bundle.js +++ b/adminforth/commands/bundle.js @@ -1,8 +1,9 @@ import { callTsProxy, findAdminInstance } from "./callTsProxy.js"; +import { afLogger } from '../modules/logger.js'; async function bundle() { - console.log("Bundling admin SPA..."); + afLogger.info("Bundling admin SPA..."); const instance = await findAdminInstance(); @@ -16,7 +17,7 @@ async function bundle() { `); } catch (e) { - console.log(`Running budndle failed`, e); + afLogger.error(`Running bundle failed`, e); } } diff --git a/adminforth/commands/callTsProxy.js b/adminforth/commands/callTsProxy.js index 737949025..f2bb31d87 100644 --- a/adminforth/commands/callTsProxy.js +++ b/adminforth/commands/callTsProxy.js @@ -43,7 +43,7 @@ export function callTsProxy(tsCode, silent=false) { const parsed = JSON.parse(stdout); if (!silent) { parsed.capturedLogs.forEach((log) => { - console.log(...log); + afLogger.log(...log); }); } @@ -131,4 +131,4 @@ export async function findAdminInstance() { // function exec() { // return admin.doX(); // } -// `).then(console.log).catch(console.error); +// `).then(afLogger.info).catch(afLogger.error); diff --git a/adminforth/commands/createApp/utils.js b/adminforth/commands/createApp/utils.js index 6e13a84f1..44bd751fc 100644 --- a/adminforth/commands/createApp/utils.js +++ b/adminforth/commands/createApp/utils.js @@ -12,6 +12,7 @@ import { exec } from 'child_process'; import Handlebars from 'handlebars'; import { promisify } from 'util'; import { getVersion } from '../cli.js'; +import { afLogger } from '../modules/logger.js'; const execAsync = promisify(exec); @@ -335,7 +336,6 @@ async function installDependencies(ctx, cwd) { await execAsync(`${nodeBinary} ${npmPath} install`, { cwd: customDir, env: { PATH: process.env.PATH } }), ]); } - // console.log(chalk.dim(`Dependencies installed in ${cwd} and ${customDir}: \n${res[0].stdout}${res[1].stdout}`)); } function generateFinalInstructions(skipPrismaSetup, options) { @@ -390,9 +390,9 @@ export function prepareWorkflow(options) { { title: 'šŸ“ Preparing final instructions...', task: (ctx) => { - console.log(chalk.green(`āœ… Successfully created your new Adminforth project in ${ctx.projectDir}!\n`)); - console.log(generateFinalInstructions(ctx.skipPrismaSetup, options)); - console.log('\n\n'); + afLogger.info(chalk.green(`āœ… Successfully created your new Adminforth project in ${ctx.projectDir}!\n`)); + afLogger.info(generateFinalInstructions(ctx.skipPrismaSetup, options)); + afLogger.info('\n\n'); } } ], diff --git a/adminforth/commands/createCustomComponent/configLoader.js b/adminforth/commands/createCustomComponent/configLoader.js index d7029d783..5f4c0ad10 100644 --- a/adminforth/commands/createCustomComponent/configLoader.js +++ b/adminforth/commands/createCustomComponent/configLoader.js @@ -3,6 +3,7 @@ import path from 'path'; import chalk from 'chalk'; import jiti from 'jiti'; import dotenv, { config } from "dotenv"; +import { afLogger } from '../modules/logger.js'; dotenv.config({ path: '.env.local', override: true }); dotenv.config({ path: '.env', override: true }); @@ -59,12 +60,12 @@ export async function loadAdminForthConfig() { } - console.log(chalk.dim(`Loaded configuration from ${configPath}`)); + afLogger.info(chalk.dim(`Loaded configuration from ${configPath}`)); return config; } catch (error) { - console.error(chalk.red(`\nError loading or parsing configuration file: ${configPath}, error: ${error}`)); - console.error(error); + afLogger.error(chalk.red(`\nError loading or parsing configuration file: ${configPath}, error: ${error}`)); + afLogger.error(error); process.exit(1); } } diff --git a/adminforth/commands/createCustomComponent/configUpdater.js b/adminforth/commands/createCustomComponent/configUpdater.js index 2ed43e1ba..e64c04561 100644 --- a/adminforth/commands/createCustomComponent/configUpdater.js +++ b/adminforth/commands/createCustomComponent/configUpdater.js @@ -3,6 +3,7 @@ import path from 'path'; import chalk from 'chalk'; import recast from 'recast'; // Import recast import * as typescriptParser from 'recast/parsers/typescript.js'; // Import the parser using ESM and include the .js extension +import { afLogger } from '../modules/logger.js'; const b = recast.types.builders; // Like t.* in babel/types const n = recast.types.namedTypes; // Like t.is* in babel/types @@ -11,7 +12,7 @@ const n = recast.types.namedTypes; // Like t.is* in babel/types async function findResourceFilePath(resourceId) { const projectRoot = process.cwd(); const resourcesDir = path.resolve(projectRoot, 'resources'); - console.log(chalk.dim(`Scanning for resource files in: ${resourcesDir}`)); + afLogger.info(chalk.dim(`Scanning for resource files in: ${resourcesDir}`)); let tsFiles = []; try { @@ -29,7 +30,7 @@ async function findResourceFilePath(resourceId) { for (const file of tsFiles) { const filePath = path.resolve(resourcesDir, file); - console.log(chalk.dim(`Attempting to process file: ${file}`)); + afLogger.info(chalk.dim(`Attempting to process file: ${file}`)); try { const content = await fs.readFile(filePath, 'utf-8'); const ast = recast.parse(content, { @@ -79,7 +80,7 @@ async function findResourceFilePath(resourceId) { ); if (resourceIdProp) { foundResourceId = resourceIdProp.value.value; // Get the string value - console.log(chalk.dim(` Extracted resourceId '${foundResourceId}' from ${file}`)); + afLogger.info(chalk.dim(` Extracted resourceId '${foundResourceId}' from ${file}`)); this.abort(); // Stop traversal for this file once found } } @@ -87,17 +88,17 @@ async function findResourceFilePath(resourceId) { } }); - console.log(chalk.dim(` Finished processing ${file}. Found resourceId: ${foundResourceId || 'null'}`)); + afLogger.info(chalk.dim(` Finished processing ${file}. Found resourceId: ${foundResourceId || 'null'}`)); if (foundResourceId === resourceId) { - console.log(chalk.dim(` Match found! Returning path: ${filePath}`)); + afLogger.info(chalk.dim(` Match found! Returning path: ${filePath}`)); return filePath; } } catch (parseError) { if (parseError.message.includes('require is not defined')) { - console.error(chalk.red(`āŒ Internal Error: Failed to load Recast parser in ESM context for ${file}.`)); + afLogger.error(chalk.red(`āŒ Internal Error: Failed to load Recast parser in ESM context for ${file}.`)); } else { - console.warn(chalk.yellow(`āš ļø Warning: Could not process file ${file}. Skipping. Error: ${parseError.message}`)); + afLogger.warn(chalk.yellow(`āš ļø Warning: Could not process file ${file}. Skipping. Error: ${parseError.message}`)); } } } @@ -108,15 +109,15 @@ async function findResourceFilePath(resourceId) { export async function updateResourceConfig(resourceId, columnName, fieldType, componentPathForConfig) { const filePath = await findResourceFilePath(resourceId); - console.log(chalk.dim(`Attempting to update resource config: ${filePath}`)); + afLogger.info(chalk.dim(`Attempting to update resource config: ${filePath}`)); let content; let injectionLine = null; try { content = await fs.readFile(filePath, 'utf-8'); } catch (error) { - console.error(chalk.red(`āŒ Error reading resource file: ${filePath}`)); - console.error(error); + afLogger.error(chalk.red(`āŒ Error reading resource file: ${filePath}`)); + afLogger.error(error); throw new Error(`Could not read resource file ${filePath}.`); } @@ -198,10 +199,10 @@ export async function updateResourceConfig(resourceId, columnName, fieldType, co const nameIndex = targetColumn.properties.findIndex(p => n.ObjectProperty.check(p) && n.Identifier.check(p.key) && p.key.name === 'name'); targetColumn.properties.splice(nameIndex !== -1 ? nameIndex + 1 : targetColumn.properties.length, 0, componentsProperty); - console.log(chalk.dim(`Added 'components' object to column '${columnName}'.`)); + afLogger.info(chalk.dim(`Added 'components' object to column '${columnName}'.`)); } else if (!n.ObjectExpression.check(componentsProperty.value)) { - console.warn(chalk.yellow(`Warning: 'components' property in column '${columnName}' is not an object. Skipping update.`)); + afLogger.warn(chalk.yellow(`Warning: 'components' property in column '${columnName}' is not an object. Skipping update.`)); return false; } @@ -215,7 +216,7 @@ export async function updateResourceConfig(resourceId, columnName, fieldType, co if (fieldTypeProperty) { injectionLine = fieldTypeProperty.loc?.start.line ?? null; fieldTypeProperty.value = newComponentValue; - console.log(chalk.dim(`Updated '${fieldType}' component path in column '${columnName}'.`)); + afLogger.info(chalk.dim(`Updated '${fieldType}' component path in column '${columnName}'.`)); } else { fieldTypeProperty = b.objectProperty(b.identifier(fieldType), newComponentValue); componentsObject.properties.push(fieldTypeProperty); @@ -223,7 +224,7 @@ export async function updateResourceConfig(resourceId, columnName, fieldType, co n.ObjectProperty.check(p) && n.Identifier.check(p.key) && p.key.name === fieldType ); injectionLine = fieldTypeProperty.loc?.start.line ?? null; - console.log(chalk.dim(`Added '${fieldType}' component path to column '${columnName}'.`)); + afLogger.info(chalk.dim(`Added '${fieldType}' component path to column '${columnName}'.`)); } updateApplied = true; @@ -239,7 +240,7 @@ export async function updateResourceConfig(resourceId, columnName, fieldType, co const outputCode = recast.print(ast).code; await fs.writeFile(filePath, outputCode, 'utf-8'); - console.log( + afLogger.info( chalk.green( `āœ… Successfully updated CRUD injection in resource file: ${filePath}` + (injectionLine !== null ? `:${injectionLine}` : '') @@ -255,7 +256,7 @@ export async function updateResourceConfig(resourceId, columnName, fieldType, co export async function injectLoginComponent(indexFilePath, componentPath, injectionType) { - console.log(chalk.dim(`Reading file: ${indexFilePath}`)); + afLogger.info(chalk.dim(`Reading file: ${indexFilePath}`)); const content = await fs.readFile(indexFilePath, 'utf-8'); const ast = recast.parse(content, { parser: typescriptParser, @@ -283,7 +284,7 @@ export async function injectLoginComponent(indexFilePath, componentPath, injecti const newObj = b.objectExpression([]); prop = b.objectProperty(b.identifier(name), newObj); obj.properties.push(prop); - console.log(chalk.dim(`Added missing '${name}' property.`)); + afLogger.info(chalk.dim(`Added missing '${name}' property.`)); } return prop.value; }; @@ -310,9 +311,9 @@ export async function injectLoginComponent(indexFilePath, componentPath, injecti b.stringLiteral(currentVal.value), b.stringLiteral(componentPath), ]); - console.log(chalk.dim(`Converted '${targetProperty}' to array with existing + new path.`)); + afLogger.info(chalk.dim(`Converted '${targetProperty}' to array with existing + new path.`)); } else { - console.log(chalk.dim(`Component path already present as string. Skipping.`)); + afLogger.info(chalk.dim(`Component path already present as string. Skipping.`)); } } else if (n.ArrayExpression.check(currentVal)) { const exists = currentVal.elements.some( @@ -320,12 +321,12 @@ export async function injectLoginComponent(indexFilePath, componentPath, injecti ); if (!exists) { currentVal.elements.push(b.stringLiteral(componentPath)); - console.log(chalk.dim(`Appended new component path to existing '${targetProperty}' array.`)); + afLogger.info(chalk.dim(`Appended new component path to existing '${targetProperty}' array.`)); } else { - console.log(chalk.dim(`Component path already present in array. Skipping.`)); + afLogger.info(chalk.dim(`Component path already present in array. Skipping.`)); } } else { - console.warn(chalk.yellow(`āš ļø '${targetProperty}' is not a string or array. Skipping.`)); + afLogger.warn(chalk.yellow(`āš ļø '${targetProperty}' is not a string or array. Skipping.`)); return false; } } else { @@ -335,11 +336,11 @@ export async function injectLoginComponent(indexFilePath, componentPath, injecti ); if (newProperty.loc) { - console.log(chalk.dim(`Adding '${targetProperty}' at line: ${newProperty.loc.start.line}`)); + afLogger.info(chalk.dim(`Adding '${targetProperty}' at line: ${newProperty.loc.start.line}`)); } loginPageInjections.properties.push(newProperty); - console.log(chalk.dim(`Added '${targetProperty}': ${componentPath}`)); + afLogger.info(chalk.dim(`Added '${targetProperty}': ${componentPath}`)); } updated = true; @@ -355,7 +356,7 @@ export async function injectLoginComponent(indexFilePath, componentPath, injecti const outputCode = recast.print(ast).code; await fs.writeFile(indexFilePath, outputCode, 'utf-8'); - console.log( + afLogger.info( chalk.green( `āœ… Successfully updated login ${targetProperty} injection in: ${indexFilePath}` + (injectionLine !== null ? `:${injectionLine}` : '') @@ -365,7 +366,7 @@ export async function injectLoginComponent(indexFilePath, componentPath, injecti export async function injectGlobalComponent(indexFilePath, injectionType, componentPath) { - console.log(chalk.dim(`Reading file: ${indexFilePath}`)); + afLogger.info(chalk.dim(`Reading file: ${indexFilePath}`)); const content = await fs.readFile(indexFilePath, 'utf-8'); const ast = recast.parse(content, { parser: typescriptParser, @@ -373,7 +374,7 @@ export async function injectGlobalComponent(indexFilePath, injectionType, compon let updated = false; let injectionLine = null; - console.log(JSON.stringify(injectionType)); + afLogger.info(JSON.stringify(injectionType)); recast.visit(ast, { visitNewExpression(path) { if ( @@ -392,7 +393,7 @@ export async function injectGlobalComponent(indexFilePath, injectionType, compon const customizationObj = b.objectExpression([]); customizationProp = b.objectProperty(b.identifier('customization'), customizationObj); configObject.properties.push(customizationProp); - console.log(chalk.dim(`Added missing 'customization' property.`)); + afLogger.info(chalk.dim(`Added missing 'customization' property.`)); } const customizationValue = customizationProp.value; @@ -406,12 +407,12 @@ export async function injectGlobalComponent(indexFilePath, injectionType, compon const injectionsObj = b.objectExpression([]); globalInjections = b.objectProperty(b.identifier('globalInjections'), injectionsObj); customizationValue.properties.push(globalInjections); - console.log(chalk.dim(`Added missing 'globalInjections'.`)); + afLogger.info(chalk.dim(`Added missing 'globalInjections'.`)); } const injectionsValue = globalInjections.value; if (!n.ObjectExpression.check(injectionsValue)) return false; - console.log(JSON.stringify(injectionType)); + afLogger.info(JSON.stringify(injectionType)); let injectionProp = injectionsValue.properties.find( p => n.ObjectProperty.check(p) && n.Identifier.check(p.key) && p.key.name === injectionType ); @@ -420,13 +421,13 @@ export async function injectGlobalComponent(indexFilePath, injectionType, compon injectionLine = injectionProp.loc?.start.line ?? null; if (n.ArrayExpression.check(currentValue)) { currentValue.elements.push(b.stringLiteral(componentPath)); - console.log(chalk.dim(`Added '${componentPath}' to existing array in '${injectionType}'`)); + afLogger.info(chalk.dim(`Added '${componentPath}' to existing array in '${injectionType}'`)); } else if (n.StringLiteral.check(currentValue)) { injectionProp.value = b.arrayExpression([ b.stringLiteral(currentValue.value), b.stringLiteral(componentPath) ]); - console.log(chalk.dim(`Converted '${injectionType}' from string to array and added '${componentPath}'`)); + afLogger.info(chalk.dim(`Converted '${injectionType}' from string to array and added '${componentPath}'`)); } else { throw new Error(`Unsupported value type for '${injectionType}'. Must be string or array.`); } @@ -437,7 +438,7 @@ export async function injectGlobalComponent(indexFilePath, injectionType, compon b.arrayExpression([b.stringLiteral(componentPath)]) ) ); - console.log(chalk.dim(`Added new array for '${injectionType}' with '${componentPath}'`)); + afLogger.info(chalk.dim(`Added new array for '${injectionType}' with '${componentPath}'`)); } updated = true; @@ -453,7 +454,7 @@ export async function injectGlobalComponent(indexFilePath, injectionType, compon const outputCode = recast.print(ast).code; await fs.writeFile(indexFilePath, outputCode, 'utf-8'); - console.log( + afLogger.info( chalk.green( `āœ… Successfully updated CRUD injection in resource file: ${indexFilePath}` + (injectionLine !== null ? `:${injectionLine}` : '') @@ -463,14 +464,14 @@ export async function injectGlobalComponent(indexFilePath, injectionType, compon export async function updateCrudInjectionConfig(resourceId, crudType, injectionPosition, componentPathForConfig, isThin) { const filePath = await findResourceFilePath(resourceId); - console.log(chalk.dim(`Attempting to update resource CRUD injection: ${filePath}`)); + afLogger.info(chalk.dim(`Attempting to update resource CRUD injection: ${filePath}`)); let content; let injectionLine = null; try { content = await fs.readFile(filePath, 'utf-8'); } catch (error) { - console.error(chalk.red(`āŒ Error reading resource file: ${filePath}`)); + afLogger.error(chalk.red(`āŒ Error reading resource file: ${filePath}`)); throw new Error(`Could not read resource file ${filePath}.`); } @@ -564,21 +565,21 @@ export async function updateCrudInjectionConfig(resourceId, crudType, injectionP if (injectionProp) { if (n.ArrayExpression.check(injectionProp.value)) { injectionProp.value.elements.push(newInjectionObject); - console.log(chalk.dim(`Appended new injection to array at '${injectionPosition}' for '${crudType}'.`)); + afLogger.info(chalk.dim(`Appended new injection to array at '${injectionPosition}' for '${crudType}'.`)); } else if (n.ObjectExpression.check(injectionProp.value)) { injectionProp.value = b.arrayExpression([injectionProp.value, newInjectionObject]); - console.log(chalk.dim(`Converted to array and added new injection at '${injectionPosition}' for '${crudType}'.`)); + afLogger.info(chalk.dim(`Converted to array and added new injection at '${injectionPosition}' for '${crudType}'.`)); } else { injectionProp.value = b.arrayExpression([newInjectionObject]); - console.log(chalk.yellow(`āš ļø Replaced invalid injection at '${injectionPosition}' with array.`)); + afLogger.warn(chalk.yellow(`āš ļø Replaced invalid injection at '${injectionPosition}' with array.`)); } } else { crudValue.properties.push( b.objectProperty(b.identifier(injectionPosition), b.arrayExpression([newInjectionObject])) ); - console.log(chalk.dim(`Added new array of injections at '${injectionPosition}' for '${crudType}'.`)); + afLogger.info(chalk.dim(`Added new array of injections at '${injectionPosition}' for '${crudType}'.`)); } updateApplied = true; @@ -593,7 +594,7 @@ export async function updateCrudInjectionConfig(resourceId, crudType, injectionP const outputCode = recast.print(ast).code; await fs.writeFile(filePath, outputCode, 'utf-8'); - console.log( + afLogger.info( chalk.green( `āœ… Successfully updated CRUD injection in resource file: ${filePath}` + (injectionLine !== null ? `:${injectionLine}` : '') @@ -601,7 +602,7 @@ export async function updateCrudInjectionConfig(resourceId, crudType, injectionP ); } catch (error) { - console.error(chalk.red(`āŒ Error processing resource file: ${filePath}`)); + afLogger.error(chalk.red(`āŒ Error processing resource file: ${filePath}`)); throw new Error(`Failed to inject CRUD component in ${path.basename(filePath)}: ${error.message}`); } } \ No newline at end of file diff --git a/adminforth/commands/createCustomComponent/fileGenerator.js b/adminforth/commands/createCustomComponent/fileGenerator.js index d6c281d6a..896c49516 100644 --- a/adminforth/commands/createCustomComponent/fileGenerator.js +++ b/adminforth/commands/createCustomComponent/fileGenerator.js @@ -4,6 +4,7 @@ import path from 'path'; import chalk from 'chalk'; import Handlebars from 'handlebars'; import { fileURLToPath } from 'url'; +import { afLogger } from '../modules/logger.js'; async function renderHBSTemplate(templatePath, data) { try { @@ -31,7 +32,7 @@ async function generateVueContent(fieldType, { resource, column }) { ? path.join(__dirname, 'templates', 'customFields', `${fieldType}.vue.hbs`) : path.join(__dirname, 'templates', 'customCrud', `${fieldType}.vue.hbs`); - console.log(chalk.dim(`Using template: ${templatePath}`)); + afLogger.info(chalk.dim(`Using template: ${templatePath}`)); const context = { componentName, @@ -61,24 +62,24 @@ export async function generateComponentFile(componentFileName, fieldType, contex const customDirPath = path.resolve(projectRoot, customDirRelative); const absoluteComponentPath = path.resolve(customDirPath, componentFileName); if (fsSync.existsSync(absoluteComponentPath)) { - console.log(chalk.yellow(`āš ļø Component file already exists: ${absoluteComponentPath}`)); + afLogger.warn(chalk.yellow(`āš ļø Component file already exists: ${absoluteComponentPath}`)); return {"alreadyExists": true, "path": absoluteComponentPath} } try { await fs.mkdir(customDirPath, { recursive: true }); - console.log(chalk.dim(`Ensured custom directory exists: ${customDirPath}`)); + afLogger.info(chalk.dim(`Ensured custom directory exists: ${customDirPath}`)); const fileContent = await generateVueContent(fieldType, context); await fs.writeFile(absoluteComponentPath, fileContent, 'utf-8'); - console.log(chalk.green(`āœ… Generated component file: ${absoluteComponentPath}`)); + afLogger.info(chalk.green(`āœ… Generated component file: ${absoluteComponentPath}`)); return {"alreadyExists": false, "path": absoluteComponentPath} } catch (error) { - console.error(chalk.red(`āŒ Error creating component file at ${absoluteComponentPath}:`)); + afLogger.error(chalk.red(`āŒ Error creating component file at ${absoluteComponentPath}:`)); if (!error.message.includes('template')) { - console.error(error); + afLogger.error(error); } throw error; } @@ -91,22 +92,22 @@ export async function generateCrudInjectionComponent(componentFileName, crudType const absoluteComponentPath = path.resolve(customDirPath, componentFileName); if (fsSync.existsSync(absoluteComponentPath)) { - console.log(chalk.yellow(`āš ļø Component file already exists: ${absoluteComponentPath}`)); + afLogger.warn(chalk.yellow(`āš ļø Component file already exists: ${absoluteComponentPath}`)); return { alreadyExists: true, path: absoluteComponentPath }; } try { await fs.mkdir(customDirPath, { recursive: true }); - console.log(chalk.dim(`Ensured custom directory exists: ${customDirPath}`)); + afLogger.warn(chalk.dim(`Ensured custom directory exists: ${customDirPath}`)); const fileContent = await generateVueContent(crudType, context); await fs.writeFile(absoluteComponentPath, fileContent, 'utf-8'); - console.log(chalk.green(`āœ… Generated component file: ${absoluteComponentPath}`)); + afLogger.info(chalk.green(`āœ… Generated component file: ${absoluteComponentPath}`)); return { alreadyExists: false, path: absoluteComponentPath }; } catch (error) { - console.error(chalk.red(`āŒ Error creating component file at ${absoluteComponentPath}:`)); + afLogger.error(chalk.red(`āŒ Error creating component file at ${absoluteComponentPath}:`)); throw error; } } @@ -118,13 +119,13 @@ export async function generateLoginOrGlobalComponentFile(componentFileName, inje const absoluteComponentPath = path.resolve(customDirPath, componentFileName); if (fsSync.existsSync(absoluteComponentPath)) { - console.log(chalk.yellow(`āš ļø Component file already exists: ${absoluteComponentPath}`)); + afLogger.warn(chalk.yellow(`āš ļø Component file already exists: ${absoluteComponentPath}`)); return { alreadyExists: true, path: absoluteComponentPath }; } try { await fs.mkdir(customDirPath, { recursive: true }); - console.log(chalk.dim(`Ensured custom directory exists: ${customDirPath}`)); + afLogger.warn(chalk.dim(`Ensured custom directory exists: ${customDirPath}`)); const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); @@ -138,11 +139,11 @@ export async function generateLoginOrGlobalComponentFile(componentFileName, inje const fileContent = await renderHBSTemplate(templatePath, context); await fs.writeFile(absoluteComponentPath, fileContent, 'utf-8'); - console.log(chalk.green(`āœ… Generated login injection component: ${absoluteComponentPath}`)); + afLogger.info(chalk.green(`āœ… Generated login injection component: ${absoluteComponentPath}`)); return { alreadyExists: false, path: absoluteComponentPath }; } catch (error) { - console.error(chalk.red(`āŒ Error creating login component at ${absoluteComponentPath}`)); + afLogger.error(chalk.red(`āŒ Error creating login component at ${absoluteComponentPath}`)); throw error; } } diff --git a/adminforth/commands/createCustomComponent/main.js b/adminforth/commands/createCustomComponent/main.js index 2b62eb65c..1da3415ef 100644 --- a/adminforth/commands/createCustomComponent/main.js +++ b/adminforth/commands/createCustomComponent/main.js @@ -4,6 +4,7 @@ import path from 'path'; import { loadAdminForthConfig } from './configLoader.js'; // Helper to load config import { generateComponentFile, generateLoginOrGlobalComponentFile, generateCrudInjectionComponent } from './fileGenerator.js'; // Helper to create the .vue file import { updateResourceConfig, injectLoginComponent, injectGlobalComponent, updateCrudInjectionConfig } from './configUpdater.js'; // Helper to modify resource .ts file +import { afLogger } from '../modules/logger.js'; function sanitizeLabel(input){ return input @@ -14,7 +15,7 @@ function sanitizeLabel(input){ } export default async function createComponent(args) { - console.log('This command will help you to generate boilerplate for component.\n'); + afLogger.info('This command will help you to generate boilerplate for component.\n'); const config = await loadAdminForthConfig(); const resources = config.resources; diff --git a/adminforth/commands/postinstall.js b/adminforth/commands/postinstall.js index 23e21cd35..bc7fa6075 100644 --- a/adminforth/commands/postinstall.js +++ b/adminforth/commands/postinstall.js @@ -2,14 +2,16 @@ import fs from 'fs'; import path from 'path'; import { execSync } from 'child_process'; +import { afLogger } from '../modules/logger.js'; + const spaPath = path.join(import.meta.dirname, 'dist', 'spa'); if (fs.existsSync(spaPath)){ - console.log('Installing SPA dependencies...'); + afLogger.info('Installing SPA dependencies...'); execSync('npm ci', { cwd: spaPath, stdio: 'inherit' }); - console.log('Installed spa dependencies'); + afLogger.info('Installed spa dependencies'); } else { - console.log('SPA dependencies not found'); - console.log('current directory', import.meta.dirname); + afLogger.warn('SPA dependencies not found'); + afLogger.info('current directory', import.meta.dirname); } \ No newline at end of file diff --git a/adminforth/commands/utils.js b/adminforth/commands/utils.js index 2f5492d8e..4bb03b6bb 100644 --- a/adminforth/commands/utils.js +++ b/adminforth/commands/utils.js @@ -1,6 +1,7 @@ import path from "path"; import { execSync } from "child_process"; import fs from "fs"; +import { afLogger } from '../modules/logger.js'; export const toPascalCase = (str) => { return str @@ -131,7 +132,7 @@ export async function getInstance(file, currentDirectory) { let filePath = initialFilePath; if (file.endsWith(".ts")) { - console.log(`Compiling TypeScript file: ${file}`); + afLogger.info(`Compiling TypeScript file: ${file}`); try { execSync( `./node_modules/.bin/tsc ${filePath} --module ESNext --outDir ./dist`, @@ -140,7 +141,7 @@ export async function getInstance(file, currentDirectory) { } ); } catch (error) { - //console.log(`Error: Could not compile TypeScript file '${file}'`); + afLogger.error(`Error: Could not compile TypeScript file '${file}'`); } const distDir = path.join(currentDirectory, "dist"); processJsFilesInDir(distDir); diff --git a/adminforth/dataConnectors/baseConnector.ts b/adminforth/dataConnectors/baseConnector.ts index 234d8d641..e9b293ad2 100644 --- a/adminforth/dataConnectors/baseConnector.ts +++ b/adminforth/dataConnectors/baseConnector.ts @@ -81,7 +81,6 @@ export default class AdminForthBaseConnector implements IAdminForthDataSourceCon // in case column isArray and enumerator/foreign resource - IN filter must be transformed into OR filter if (filterValidation.ok && f.operator == AdminForthFilterOperators.IN) { const column = resource.dataSourceColumns.find((col) => col.name == (f as IAdminForthSingleFilter).field); - // console.log(`\n~~~ column: ${JSON.stringify(column, null, 2)}\n~~~ resource.columns: ${JSON.stringify(resource.dataSourceColumns, null, 2)}\n~~~ filter: ${JSON.stringify(f, null, 2)}\n`); if (column.isArray?.enabled && (column.enum || column.foreignResource)) { filters[fIndex] = { operator: AdminForthFilterOperators.OR, diff --git a/adminforth/dataConnectors/mongo.ts b/adminforth/dataConnectors/mongo.ts index d6b58f786..82b4913bb 100644 --- a/adminforth/dataConnectors/mongo.ts +++ b/adminforth/dataConnectors/mongo.ts @@ -3,7 +3,7 @@ import { MongoClient } from 'mongodb'; import { Decimal128, Double } from 'bson'; import { IAdminForthDataSourceConnector, IAdminForthSingleFilter, IAdminForthAndOrFilter, AdminForthResource } from '../types/Back.js'; import AdminForthBaseConnector from './baseConnector.js'; - +import { afLogger } from '../modules/logger.js'; import { AdminForthDataTypes, AdminForthFilterOperators, AdminForthSortDirections, } from '../types/Common.js'; const escapeRegex = (value) => { @@ -36,11 +36,11 @@ class MongoConnector extends AdminForthBaseConnector implements IAdminForthDataS try { await this.client.connect(); this.client.on('error', (err) => { - console.log('Mongo error: ', err.message) + afLogger.error(`Mongo error: ${err.message}`); }); - console.log('Connected to Mongo'); + afLogger.info('Connected to Mongo'); } catch (e) { - console.error(`Failed to connect to Mongo: ${e}`); + afLogger.error(`Failed to connect to Mongo: ${e}`); } })(); } diff --git a/adminforth/dataConnectors/postgres.ts b/adminforth/dataConnectors/postgres.ts index b3e7fca77..89adf7271 100644 --- a/adminforth/dataConnectors/postgres.ts +++ b/adminforth/dataConnectors/postgres.ts @@ -3,7 +3,7 @@ import { AdminForthResource, IAdminForthSingleFilter, IAdminForthAndOrFilter, IA import { AdminForthDataTypes, AdminForthFilterOperators, AdminForthSortDirections, } from '../types/Common.js'; import AdminForthBaseConnector from './baseConnector.js'; import pkg from 'pg'; -import { dbLogger } from '../modules/logger.js'; +import { afLogger, dbLogger } from '../modules/logger.js'; const { Client } = pkg; @@ -17,7 +17,7 @@ class PostgresConnector extends AdminForthBaseConnector implements IAdminForthDa try { await this.client.connect(); this.client.on('error', async (err) => { - console.log('Postgres error: ', err.message, err.stack) + afLogger.error(`Postgres error: ${err.message} ${err.stack}`); this.client.end(); await new Promise((resolve) => { setTimeout(resolve, 1000) }); this.setupClient(url); @@ -406,8 +406,6 @@ class PostgresConnector extends AdminForthBaseConnector implements IAdminForthDa } const primaryKey = this.getPrimaryKey(resource); const q = `INSERT INTO "${tableName}" (${columns.join(', ')}) VALUES (${placeholders}) RETURNING "${primaryKey}"`; - // console.log('\nšŸ”µ [PG INSERT]:', q); - // console.log('šŸ“¦ [VALUES]:', JSON.stringify(values, null, 2)); dbLogger.trace(`šŸŖ²šŸ“œ PG Q: ${q}, values: ${JSON.stringify(values)}`); const ret = await this.client.query(q, values); return ret.rows[0][primaryKey]; diff --git a/adminforth/dataConnectors/sqlite.ts b/adminforth/dataConnectors/sqlite.ts index 2c4aa253c..7331a7ecf 100644 --- a/adminforth/dataConnectors/sqlite.ts +++ b/adminforth/dataConnectors/sqlite.ts @@ -335,10 +335,7 @@ class SQLiteConnector extends AdminForthBaseConnector implements IAdminForthData const columns = Object.keys(record); const placeholders = columns.map(() => '?').join(', '); const values = columns.map((colName) => record[colName]); - // const q = this.client.prepare(`INSERT INTO ${tableName} (${columns.join(', ')}) VALUES (${placeholders})`); const sql = `INSERT INTO ${tableName} (${columns.join(', ')}) VALUES (${placeholders})`; - //console.log('\n🟢 [SQLITE INSERT]:', sql); - //console.log('šŸ“¦ [VALUES]:', JSON.stringify(values, null, 2)); const q = this.client.prepare(sql); dbLogger.trace(`šŸŖ²šŸ“œ SQLITE Q: ${sql}, values: ${JSON.stringify(values)}`); const ret = await q.run(values); diff --git a/adminforth/index.ts b/adminforth/index.ts index de4f62361..67705ad81 100644 --- a/adminforth/index.ts +++ b/adminforth/index.ts @@ -176,7 +176,7 @@ class AdminForth implements IAdminForth { dbDiscover: 'running', }; - console.log(`${this.formatAdminForth()} v${ADMINFORTH_VERSION} initializing...`); + console.info(`${this.formatAdminForth()} v${ADMINFORTH_VERSION} initializing...`); afLogger.trace('šŸ”§ About to set global.adminforth...'); global.adminforth = this; afLogger.trace('šŸ”§ global.adminforth set successfully'); @@ -441,13 +441,11 @@ class AdminForth implements IAdminForth { this.operationalResources[resource.resourceId] = new OperationalResource(this.connectors[resource.dataSource], resource); }); - // console.log('āš™ļøāš™ļøāš™ļø Database discovery done', JSON.stringify(this.config.resources, null, 2)); } async getAllTables(): Promise<{ [dataSourceId: string]: string[] }> { const results: { [dataSourceId: string]: string[] } = {}; - // console.log('Connectors to process:', Object.keys(this.connectors)); if (!this.config.databaseConnectors) { this.config.databaseConnectors = {...this.connectorClasses}; } @@ -463,7 +461,6 @@ class AdminForth implements IAdminForth { results[dataSourceId] = []; } } else { - // console.log(`Connector ${dataSourceId} does not have getAllTables method`); results[dataSourceId] = []; } }) @@ -552,7 +549,7 @@ class AdminForth implements IAdminForth { // execute hook if needed for (const hook of listify(resource.hooks?.create?.beforeSave)) { - console.log('🪲 Hook beforeSave', hook); + console.debug('🪲 Hook beforeSave', hook); const resp = await hook({ resource, record, From c3ae78b2483e144490e556366e610783bcbcee85 Mon Sep 17 00:00:00 2001 From: yaroslav8765 Date: Sat, 10 Jan 2026 14:53:07 +0200 Subject: [PATCH 7/7] chore: use logger instead of console.log --- .../createApp/templates/adminuser.ts.hbs | 4 +-- .../commands/createApp/templates/index.ts.hbs | 6 ++--- .../blog/2024-10-01-ai-blog/index.md | 6 ++--- .../docs/tutorial/01-helloWorld.md | 8 +++--- .../tutorial/03-Customization/09-Actions.md | 2 +- .../tutorial/03-Customization/16-websocket.md | 5 ++-- .../tutorial/05-Plugins/15-email-invite.md | 3 ++- .../tutorial/07-Plugins/16-email-invite.md | 3 ++- adminforth/index.ts | 3 ++- adminforth/modules/codeInjector.ts | 27 +++++++------------ adminforth/modules/restApi.ts | 5 ++-- adminforth/servers/express.ts | 3 +-- adminforth/spa/src/afcl/DatePicker.vue | 1 - .../src/components/CustomDateRangePicker.vue | 2 -- .../spa/src/components/CustomRangePicker.vue | 2 -- dev-demo/index.ts | 5 ++-- dev-demo/resources/adminuser.ts | 4 +-- dev-demo/resources/carsResourseTemplate.ts | 5 +++- 18 files changed, 43 insertions(+), 51 deletions(-) diff --git a/adminforth/commands/createApp/templates/adminuser.ts.hbs b/adminforth/commands/createApp/templates/adminuser.ts.hbs index 0eb77905f..494c7577f 100644 --- a/adminforth/commands/createApp/templates/adminuser.ts.hbs +++ b/adminforth/commands/createApp/templates/adminuser.ts.hbs @@ -1,5 +1,5 @@ import AdminForth, { AdminForthDataTypes } from 'adminforth'; -import type { AdminForthResourceInput, AdminForthResource, AdminUser } from 'adminforth'; +import type { AdminForthResourceInput, AdminForthResource, AdminUser, logger } from 'adminforth'; import { randomUUID } from 'crypto'; async function allowedForSuperAdmin({ adminUser }: { adminUser: AdminUser }): Promise { @@ -94,7 +94,7 @@ export default { }, edit: { beforeSave: async ({ oldRecord, updates, adminUser, resource }: { oldRecord: any, updates: any, adminUser: AdminUser, resource: AdminForthResource }) => { - console.log('Updating user', updates); + logger.info('Updating user', updates); if (oldRecord.id === adminUser.dbUser.id && updates.role) { return { ok: false, error: 'You cannot change your own role' }; } diff --git a/adminforth/commands/createApp/templates/index.ts.hbs b/adminforth/commands/createApp/templates/index.ts.hbs index ae7722b08..38696c2ab 100644 --- a/adminforth/commands/createApp/templates/index.ts.hbs +++ b/adminforth/commands/createApp/templates/index.ts.hbs @@ -3,7 +3,7 @@ import AdminForth from 'adminforth'; import usersResource from "./resources/adminuser.js"; import { fileURLToPath } from 'url'; import path from 'path'; -import { Filters } from 'adminforth'; +import { Filters, logger } from 'adminforth'; import { initApi } from './api.js'; const ADMIN_BASE_URL = ''; @@ -75,7 +75,7 @@ if (fileURLToPath(import.meta.url) === path.resolve(process.argv[1])) { const port = 3500; admin.bundleNow({ hotReload: process.env.NODE_ENV === 'development' }).then(() => { - console.log('Bundling AdminForth SPA done.'); + logger.info('Bundling AdminForth SPA done.'); }); admin.express.serve(app); @@ -91,6 +91,6 @@ if (fileURLToPath(import.meta.url) === path.resolve(process.argv[1])) { }); admin.express.listen(port, () => { - console.log(`\n⚔ AdminForth is available at http://localhost:${port}${ADMIN_BASE_URL}\n`); + logger.info(`\n⚔ AdminForth is available at http://localhost:${port}${ADMIN_BASE_URL}\n`); }); } diff --git a/adminforth/documentation/blog/2024-10-01-ai-blog/index.md b/adminforth/documentation/blog/2024-10-01-ai-blog/index.md index 8a294008b..291b4fcb7 100644 --- a/adminforth/documentation/blog/2024-10-01-ai-blog/index.md +++ b/adminforth/documentation/blog/2024-10-01-ai-blog/index.md @@ -212,7 +212,7 @@ Open `index.ts` file in root directory and update it with the following content: ```ts title="./index.ts" import express from 'express'; -import AdminForth, { Filters, Sorts } from 'adminforth'; +import AdminForth, { Filters, Sorts, logger } from 'adminforth'; import userResource from './resources/adminuser.js'; import postResource from './resources/posts.js'; import contentImageResource from './resources/content-image.js'; @@ -287,7 +287,7 @@ if (import.meta.url === `file://${process.argv[1]}`) { const port = 3500; admin.bundleNow({ hotReload: process.env.NODE_ENV === 'development' }).then(() => { - console.log('Bundling AdminForth SPA done.'); + logger.info('Bundling AdminForth SPA done.'); }); // api to server recent posts @@ -343,7 +343,7 @@ if (import.meta.url === `file://${process.argv[1]}`) { }); admin.express.listen(port, () => { - console.log(`\n⚔ AdminForth is available at http://localhost:${port}/admin\n`) + logger.info(`\n⚔ AdminForth is available at http://localhost:${port}/admin\n`) }); } ``` diff --git a/adminforth/documentation/docs/tutorial/01-helloWorld.md b/adminforth/documentation/docs/tutorial/01-helloWorld.md index 24db51226..f5a79f3d5 100644 --- a/adminforth/documentation/docs/tutorial/01-helloWorld.md +++ b/adminforth/documentation/docs/tutorial/01-helloWorld.md @@ -131,7 +131,7 @@ Create `index.ts` file in root directory with following content: ```ts title="./index.ts" import express from 'express'; -import AdminForth, { AdminForthDataTypes, Filters } from 'adminforth'; +import AdminForth, { AdminForthDataTypes, Filters, logger } from 'adminforth'; import type { AdminForthResourceInput, AdminForthResource, AdminUser } from 'adminforth'; export const admin = new AdminForth({ @@ -218,7 +218,7 @@ export const admin = new AdminForth({ }, edit: { beforeSave: async ({ oldRecord, updates, adminUser, resource }: { oldRecord: any, updates: any, adminUser: AdminUser, resource: AdminForthResource }) => { - console.log('Updating user', updates); + logger.info('Updating user', updates); if (oldRecord.id === adminUser.dbUser.id && updates.role) { return { ok: false, error: 'You cannot change your own role' }; } @@ -321,7 +321,7 @@ if (import.meta.url === `file://${process.argv[1]}`) { // needed to compile SPA. Call it here or from a build script e.g. in Docker build time to reduce downtime admin.bundleNow({ hotReload: process.env.NODE_ENV === 'development' }).then(() => { - console.log('Bundling AdminForth SPA done.'); + logger.info('Bundling AdminForth SPA done.'); }); // serve after you added all api @@ -338,7 +338,7 @@ if (import.meta.url === `file://${process.argv[1]}`) { }); admin.express.listen(port, () => { - console.log(`\n⚔ AdminForth is available at http://localhost:${port}\n`) + logger.info(`\n⚔ AdminForth is available at http://localhost:${port}\n`) }); } ``` diff --git a/adminforth/documentation/docs/tutorial/03-Customization/09-Actions.md b/adminforth/documentation/docs/tutorial/03-Customization/09-Actions.md index 1d0a595cd..8e50b4897 100644 --- a/adminforth/documentation/docs/tutorial/03-Customization/09-Actions.md +++ b/adminforth/documentation/docs/tutorial/03-Customization/09-Actions.md @@ -22,7 +22,7 @@ Here's how to add a custom action: // Handler function when action is triggered action: async ({ recordId, adminUser }) => { - console.log("auto submit", recordId, adminUser); + logger.info("auto submit", recordId, adminUser); return { ok: true, successMessage: "Auto submitted" diff --git a/adminforth/documentation/docs/tutorial/03-Customization/16-websocket.md b/adminforth/documentation/docs/tutorial/03-Customization/16-websocket.md index 497fb4c42..38b18d7ed 100644 --- a/adminforth/documentation/docs/tutorial/03-Customization/16-websocket.md +++ b/adminforth/documentation/docs/tutorial/03-Customization/16-websocket.md @@ -7,10 +7,11 @@ In two words, to subscribe to a topic from any frontend component you need to do ```javascript import websocket from '@/websocket'; +import { logger } from 'adminforth' websocket.subscribe('/topic-name', (data) => { // this callback called when we receive publish in topic from the websocket - console.log(data); + logger.info(data); }); ``` @@ -192,7 +193,7 @@ const admin = new AdminForth({ //diff-add const [subject, param] = /^\/(.+?)\/(.+)/.exec(topic)!.slice(1); //diff-add - console.log(`Websocket user ${adminUser.username} tries to subscribe to topic ${subject} with param ${param}`); + logger.info(`Websocket user ${adminUser.username} tries to subscribe to topic ${subject} with param ${param}`); //diff-add if (subject === 'property-cost') { //diff-add diff --git a/adminforth/documentation/docs/tutorial/05-Plugins/15-email-invite.md b/adminforth/documentation/docs/tutorial/05-Plugins/15-email-invite.md index 261d1fce3..3fde70097 100644 --- a/adminforth/documentation/docs/tutorial/05-Plugins/15-email-invite.md +++ b/adminforth/documentation/docs/tutorial/05-Plugins/15-email-invite.md @@ -31,6 +31,7 @@ To Setup SES, you need to have an AWS account and SES service enabled. You can f ```typescript title="./resources/adminuser.ts" import EmailInvitePlugin from '@adminforth/email-invite'; import EmailAdapterAwsSes from '@adminforth/email-adapter-aws-ses'; +import { logger } from 'adminforth' export default { dataSource: 'maindb', @@ -77,7 +78,7 @@ export default { }, edit: { beforeSave: async ({ oldRecord, updates, adminUser, resource }: { oldRecord: any, updates: any, adminUser: AdminUser, resource: AdminForthResource }) => { - console.log('Updating user', updates); + logger.info('Updating user', updates); if (oldRecord.id === adminUser.dbUser.id && updates.role) { return { ok: false, error: 'You cannot change your own role' }; } diff --git a/adminforth/documentation/docs/tutorial/07-Plugins/16-email-invite.md b/adminforth/documentation/docs/tutorial/07-Plugins/16-email-invite.md index 6f2ea4b62..7ab89bf15 100644 --- a/adminforth/documentation/docs/tutorial/07-Plugins/16-email-invite.md +++ b/adminforth/documentation/docs/tutorial/07-Plugins/16-email-invite.md @@ -31,6 +31,7 @@ To Setup SES, you need to have an AWS account and SES service enabled. You can f ```typescript title="./resources/adminuser.ts" import EmailInvitePlugin from '@adminforth/email-invite'; import EmailAdapterAwsSes from '@adminforth/email-adapter-aws-ses'; +import { logger } from 'adminforth' export default { dataSource: 'maindb', @@ -77,7 +78,7 @@ export default { }, edit: { beforeSave: async ({ oldRecord, updates, adminUser, resource }: { oldRecord: any, updates: any, adminUser: AdminUser, resource: AdminForthResource }) => { - console.log('Updating user', updates); + logger.info('Updating user', updates); if (oldRecord.id === adminUser.dbUser.id && updates.role) { return { ok: false, error: 'You cannot change your own role' }; } diff --git a/adminforth/index.ts b/adminforth/index.ts index 67705ad81..a08c80537 100644 --- a/adminforth/index.ts +++ b/adminforth/index.ts @@ -35,6 +35,7 @@ import ClickhouseConnector from './dataConnectors/clickhouse.js'; import OperationalResource from './modules/operationalResource.js'; import SocketBroker from './modules/socketBroker.js'; import { afLogger } from './modules/logger.js'; +export { logger } from './modules/logger.js'; // exports export * from './types/Back.js'; @@ -176,7 +177,7 @@ class AdminForth implements IAdminForth { dbDiscover: 'running', }; - console.info(`${this.formatAdminForth()} v${ADMINFORTH_VERSION} initializing...`); + afLogger.info(`${this.formatAdminForth()} v${ADMINFORTH_VERSION} initializing...`); afLogger.trace('šŸ”§ About to set global.adminforth...'); global.adminforth = this; afLogger.trace('šŸ”§ global.adminforth set successfully'); diff --git a/adminforth/modules/codeInjector.ts b/adminforth/modules/codeInjector.ts index fb0d526b9..7f7c3c2dc 100644 --- a/adminforth/modules/codeInjector.ts +++ b/adminforth/modules/codeInjector.ts @@ -65,9 +65,9 @@ function hashify(obj) { } function notifyWatcherIssue(limit) { - console.log('Ran out of file handles after watching %s files.', limit); - console.log('Falling back to polling which uses more CPU.'); - console.log('Run ulimit -n 10000 to increase the limit for open files.'); + afLogger.info('Ran out of file handles after watching %s files.', limit); + afLogger.info('Falling back to polling which uses more CPU.'); + afLogger.info('Run ulimit -n 10000 to increase the limit for open files.'); } class CodeInjector implements ICodeInjector { @@ -92,7 +92,7 @@ class CodeInjector implements ICodeInjector { } cleanup() { - console.log('Cleaning up...'); + afLogger.info('Cleaning up...'); this.allWatchers.forEach((watcher) => { watcher.removeAll(); }); @@ -108,14 +108,6 @@ class CodeInjector implements ICodeInjector { } - // async runShell({ command }) { - // console.log(`āš™ļø Running shell ${command}...`); - // console.time(`${command} done in`); - // const { stdout: out, stderr: err } = await execAsync(command); - // console.timeEnd(`${command} done in`); - // console.log(`Command ${command} output:`, out, err); - // } - async runNpmShell({command, cwd, envOverrides = {}}: { command: string, cwd: string, @@ -511,7 +503,6 @@ class CodeInjector implements ICodeInjector { this.allComponentNames[filePath] = componentName; }); - // console.log('šŸ”§ Injecting code into Vue sources...', this.allComponentNames); let customComponentsImports = ''; for (const [targetPath, component] of Object.entries(this.allComponentNames)) { @@ -859,7 +850,7 @@ class CodeInjector implements ICodeInjector { } async bundleNow({ hotReload = false }: { hotReload: boolean }) { - console.log(`${this.adminforth.formatAdminForth()} Bundling ${hotReload ? 'and listening for changes (šŸ”„ Hotreload)' : ' (no hot reload)'}`); + afLogger.info(`${this.adminforth.formatAdminForth()} Bundling ${hotReload ? 'and listening for changes (šŸ”„ Hotreload)' : ' (no hot reload)'}`); this.adminforth.runningHotReload = hotReload; await this.prepareSources(); @@ -917,7 +908,7 @@ class CodeInjector implements ICodeInjector { // save hash await fs.promises.writeFile(path.join(serveDir, '.adminforth_messages_hash'), sourcesHash); } else { - console.log(`AdminForth i18n message extraction skipped — build already performed for the current sources.`); + afLogger.info(`AdminForth i18n message extraction skipped — build already performed for the current sources.`); } if (!hotReload) { @@ -932,14 +923,14 @@ class CodeInjector implements ICodeInjector { // save hash await fs.promises.writeFile(path.join(serveDir, '.adminforth_build_hash'), sourcesHash); } else { - console.log(`Skipping AdminForth SPA bundling - already completed for the current sources.`); + afLogger.info(`Skipping AdminForth SPA bundling - already completed for the current sources.`); } } else { const command = 'run dev'; - console.log(`āš™ļø spawn: npm ${command}...`); + afLogger.info(`āš™ļø spawn: npm ${command}...`); if (process.env.VITE_ADMINFORTH_PUBLIC_PATH) { - console.log('āš ļø Your VITE_ADMINFORTH_PUBLIC_PATH:', process.env.VITE_ADMINFORTH_PUBLIC_PATH, 'has no effect'); + afLogger.info('āš ļø Your VITE_ADMINFORTH_PUBLIC_PATH:', process.env.VITE_ADMINFORTH_PUBLIC_PATH, 'has no effect'); } const env = { VITE_ADMINFORTH_PUBLIC_PATH: this.adminforth.config.baseUrl, diff --git a/adminforth/modules/restApi.ts b/adminforth/modules/restApi.ts index 07e7bb921..1765711fd 100644 --- a/adminforth/modules/restApi.ts +++ b/adminforth/modules/restApi.ts @@ -15,7 +15,7 @@ import { Filters, } from "../types/Back.js"; -import { logger, afLogger, dbLogger } from "./logger.js"; +import { afLogger } from "./logger.js"; import { ADMINFORTH_VERSION, listify, md5hash, getLoginPromptHTML } from './utils.js'; @@ -176,7 +176,7 @@ export default class AdminForthRestAPI implements IAdminForthRestAPI { showIn: Object.values(AdminForthResourcePages).reduce((acc, page) => { return { ...acc, [page]: false } }, {} as ShowInResolved), type: AdminForthDataTypes.STRING, }); - console.log('Adding passwordHashField to userResource', userResource) + afLogger.info(`Adding passwordHashField to userResource, ${userResource}`); } const userRecord = ( @@ -208,7 +208,6 @@ export default class AdminForthRestAPI implements IAdminForthRestAPI { const expireInDuration = rememberMe ? (this.adminforth.config.auth.rememberMeDuration || '30d') : '1d'; - console.log('expireInDuration', expireInDuration); await this.processLoginCallbacks(adminUser, toReturn, response, { body, headers, query, cookies, requestUrl, diff --git a/adminforth/servers/express.ts b/adminforth/servers/express.ts index d86b8181e..bd3b29dac 100644 --- a/adminforth/servers/express.ts +++ b/adminforth/servers/express.ts @@ -114,7 +114,6 @@ class ExpressServer implements IExpressHttpServer { } await proxyTo(`http://localhost:${this.adminforth.codeInjector.devServerPort}${req.url}`, res); } catch (e) { - // console.log('Failed to proxy', e); res.status(500).send(respondNoServer('AdminForth SPA is not ready yet', 'Vite is still starting up. Please wait a moment...')); return; } @@ -173,7 +172,7 @@ class ExpressServer implements IExpressHttpServer { this.server = http.createServer(this.expressApp); const wss = new WebSocketServer({ server: this.server, path: `${base}/afws` }); - console.log(`${this.adminforth.formatAdminForth()} 🌐 WebSocket server started`); + afLogger.info(`${this.adminforth.formatAdminForth()} 🌐 WebSocket server started`); // Handle WebSocket connections wss.on('connection', async (ws, req) => { try { diff --git a/adminforth/spa/src/afcl/DatePicker.vue b/adminforth/spa/src/afcl/DatePicker.vue index b9ac32fa9..a6dd2390f 100644 --- a/adminforth/spa/src/afcl/DatePicker.vue +++ b/adminforth/spa/src/afcl/DatePicker.vue @@ -134,7 +134,6 @@ onMounted(() => { }) watch(start, () => { - //console.log('⚔ emit', start.value) emit('update:valueStart', start.value) }) diff --git a/adminforth/spa/src/components/CustomDateRangePicker.vue b/adminforth/spa/src/components/CustomDateRangePicker.vue index bb929a922..5b3e40d16 100644 --- a/adminforth/spa/src/components/CustomDateRangePicker.vue +++ b/adminforth/spa/src/components/CustomDateRangePicker.vue @@ -197,12 +197,10 @@ onMounted(() => { }) watch(start, () => { - //console.log('⚔ emit', start.value) emit('update:valueStart', start.value) }) watch(end, () => { - //console.log('⚔ emit', end.value) emit('update:valueEnd', end.value) }) diff --git a/adminforth/spa/src/components/CustomRangePicker.vue b/adminforth/spa/src/components/CustomRangePicker.vue index 6bde0aaa7..ac75b9bde 100644 --- a/adminforth/spa/src/components/CustomRangePicker.vue +++ b/adminforth/spa/src/components/CustomRangePicker.vue @@ -89,12 +89,10 @@ function updateEndFromProps() { } watch(start, () => { - console.log('⚔ emit', start.value) emit('update:valueStart', start.value) }) watch(end, () => { - console.log('⚔ emit', end.value) emit('update:valueEnd', end.value); }) diff --git a/dev-demo/index.ts b/dev-demo/index.ts index 9eea00f11..717470a87 100644 --- a/dev-demo/index.ts +++ b/dev-demo/index.ts @@ -16,6 +16,7 @@ import { FICTIONAL_CAR_BRANDS, FICTIONAL_CAR_MODELS_BY_BRAND, ENGINE_TYPES, BODY import passkeysResource from './resources/passkeys.js'; import carsDescriptionImage from './resources/cars_description_image.js'; import translations from "./resources/translations.js"; +import { logger } from 'adminforth'; const ADMIN_BASE_URL = ''; @@ -183,7 +184,7 @@ if (fileURLToPath(import.meta.url) === path.resolve(process.argv[1])) { const port = 3000; admin.bundleNow({ hotReload: process.env.NODE_ENV === 'development' }).then(() => { - console.log('Bundling AdminForth SPA done.'); + logger.info('Bundling AdminForth SPA done.'); }); admin.express.serve(app); @@ -282,6 +283,6 @@ if (fileURLToPath(import.meta.url) === path.resolve(process.argv[1])) { }); admin.express.listen(port, () => { - console.log(`\n⚔ AdminForth is available at http://localhost:${port}${ADMIN_BASE_URL}\n`); + logger.info(`⚔ AdminForth is available at http://localhost:${port}${ADMIN_BASE_URL}\n`); }); } diff --git a/dev-demo/resources/adminuser.ts b/dev-demo/resources/adminuser.ts index 89f7d5165..6cc60d787 100644 --- a/dev-demo/resources/adminuser.ts +++ b/dev-demo/resources/adminuser.ts @@ -1,4 +1,4 @@ -import AdminForth, { AdminForthDataTypes } from '../../adminforth/index.js'; +import AdminForth, { AdminForthDataTypes, logger } from '../../adminforth/index.js'; import type { AdminForthResourceInput, AdminForthResource, AdminUser, AdminForthResourceColumn } from '../../adminforth/index.js'; import { randomUUID } from 'crypto'; import TwoFactorsAuthPlugin from '../../plugins/adminforth-two-factors-auth/index.js' @@ -205,7 +205,7 @@ export default { }, edit: { beforeSave: async ({ oldRecord, updates, adminUser, resource }: { oldRecord: any, updates: any, adminUser: AdminUser, resource: AdminForthResource }) => { - console.log('Updating user', updates); + logger.info('Updating user', updates); if (oldRecord.id === adminUser.dbUser.id && updates.role) { return { ok: false, error: 'You cannot change your own role' }; } diff --git a/dev-demo/resources/carsResourseTemplate.ts b/dev-demo/resources/carsResourseTemplate.ts index b96ba61d9..0cad95a67 100644 --- a/dev-demo/resources/carsResourseTemplate.ts +++ b/dev-demo/resources/carsResourseTemplate.ts @@ -17,6 +17,8 @@ import ImageGenerationAdapterOpenAI from '../../adapters/adminforth-image-genera import AdminForthStorageAdapterLocalFilesystem from "../../adapters/adminforth-storage-adapter-local/index.js"; import AdminForthAdapterS3Storage from '../../adapters/adminforth-storage-adapter-amazon-s3/index.js'; import AdminForthImageVisionAdapterOpenAi from '../../adapters/adminforth-image-vision-adapter-openai/index.js'; +import { logger } from 'adminforth' +import { afLogger } from '../../adminforth/modules/logger.js'; export default function carsResourseTemplate(resourceId: string, dataSource: string, pkFileldName: string) { return { @@ -285,7 +287,7 @@ export default function carsResourseTemplate(resourceId: string, dataSource: str if (!record.promo_picture) { return []; } - console.log('Attaching file for analysis:', `http://localhost:3000/static/source/cars_promo_images/${record.promo_picture}`); + afLogger.info(`Attaching file for analysis: http://localhost:3000/static/source/cars_promo_images/${record.promo_picture}`); return [`http://localhost:3000/static/source/${record.promo_picture}`]; }, visionAdapter: new AdminForthImageVisionAdapterOpenAi( @@ -341,6 +343,7 @@ export default function carsResourseTemplate(resourceId: string, dataSource: str name: 'Approve Listing', icon: 'flowbite:check-outline', action: async ({ recordId, adminUser, adminforth, extra, response }) => { + logger.info(`Admin User is approving listing for record ${recordId} in resource ${resourceId}`); //@ts-ignore const verificationResult = extra?.verificationResult if (!verificationResult) {