From 11efdf32a0828c277569905c4690a9bfacebffaf Mon Sep 17 00:00:00 2001 From: yaroslav8765 Date: Fri, 9 Jan 2026 14:13:31 +0200 Subject: [PATCH 01/13] 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 02/13] 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 03/13] 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 04/13] 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 05/13] 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 06/13] 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 07/13] 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) { From b1a391fe319a6e2f896e9d557cf684c43b636cf5 Mon Sep 17 00:00:00 2001 From: yaroslav8765 Date: Mon, 12 Jan 2026 10:59:24 +0200 Subject: [PATCH 08/13] chore: replace console.error and console.warn with afLogger for consistent logging across modules --- adminforth/auth.ts | 13 +++++++------ adminforth/commands/callTsProxy.js | 4 ++-- adminforth/dataConnectors/baseConnector.ts | 2 +- adminforth/dataConnectors/clickhouse.ts | 7 ++++--- adminforth/dataConnectors/mongo.ts | 2 +- adminforth/dataConnectors/mysql.ts | 8 ++++---- adminforth/dataConnectors/postgres.ts | 6 +++--- adminforth/dataConnectors/sqlite.ts | 6 +++--- adminforth/index.ts | 12 ++++++------ adminforth/modules/codeInjector.ts | 4 ++-- adminforth/modules/configValidator.ts | 3 ++- adminforth/modules/socketBroker.ts | 4 ++-- adminforth/servers/express.ts | 12 ++++++------ 13 files changed, 43 insertions(+), 40 deletions(-) diff --git a/adminforth/auth.ts b/adminforth/auth.ts index 6faff95e0..6c8416f80 100644 --- a/adminforth/auth.ts +++ b/adminforth/auth.ts @@ -3,6 +3,7 @@ import jwt from 'jsonwebtoken'; import crypto from 'crypto'; import AdminForth from './index.js'; import { IAdminForthAuth } from './types/Back.js'; +import { afLogger } from './modules/logger.js'; // Function to generate a password hash using PBKDF2 function calcPasswordHash(password, salt, iterations = 100000, keyLength = 64, digest = 'sha512') { @@ -105,7 +106,7 @@ class AdminForthAuth implements IAdminForthAuth { if (expirySeconds !== undefined) { expiryMs = expirySeconds * 1000; } else if (expiry !== undefined) { - console.warn('setCustomCookie: expiry(in ms) is deprecated, use expirySeconds instead (seconds), traceback:', new Error().stack); + afLogger.warn(`setCustomCookie: expiry(in ms) is deprecated, use expirySeconds instead (seconds), traceback: ${new Error().stack}`); expiryMs = expiry; } @@ -145,23 +146,23 @@ class AdminForthAuth implements IAdminForthAuth { decoded = jwt.verify(jwtToken, secret); } catch (err) { if (err.name === 'TokenExpiredError') { - console.error('Token expired:', err.message); + afLogger.error(`Token expired: ${err.message}`); } else if (err.name === 'JsonWebTokenError') { - console.error('Token error:', err.message); + afLogger.error(`Token error: ${err.message}`); } else { - console.error('Failed to verify JWT token', err); + afLogger.error(`Failed to verify JWT token: ${err}`); } return null; } const { pk, t } = decoded; if (t !== mustHaveType) { - console.error(`Invalid token type during verification: ${t}, must be ${mustHaveType}`); + afLogger.error(`Invalid token type during verification: ${t}, must be ${mustHaveType}`); return null; } if (decodeUser !== false) { const dbUser = await this.adminforth.getUserByPk(pk); if (!dbUser) { - console.error(`User with pk ${pk} not found in database`); + afLogger.error(`User with pk ${pk} not found in database`); // will logout user which was deleted return null; } diff --git a/adminforth/commands/callTsProxy.js b/adminforth/commands/callTsProxy.js index f2bb31d87..8eeb5d292 100644 --- a/adminforth/commands/callTsProxy.js +++ b/adminforth/commands/callTsProxy.js @@ -55,7 +55,7 @@ export function callTsProxy(tsCode, silent=false) { reject(new Error("Invalid JSON from tsproxy: " + stdout)); } } else { - console.error(`tsproxy exited with non-0, this should never happen, stdout: ${stdout}, stderr: ${stderr}`); + afLogger.error(`tsproxy exited with non-0, this should never happen, stdout: ${stdout}, stderr: ${stderr}`); reject(new Error(stderr)); } }); @@ -102,7 +102,7 @@ export async function findAdminInstance() { // and show the error so user can fix it const fileContent = fs.readFileSync(file, "utf-8"); if (fileContent.includes("export const admin")) { - console.error(chalk.red(`Error running ${file}:`, e)); + afLogger.error(`Error running ${file}: ${e}`); process.exit(1); } afLogger.trace(`🪲 File ${file} failed`, e); diff --git a/adminforth/dataConnectors/baseConnector.ts b/adminforth/dataConnectors/baseConnector.ts index e9b293ad2..d53233753 100644 --- a/adminforth/dataConnectors/baseConnector.ts +++ b/adminforth/dataConnectors/baseConnector.ts @@ -18,7 +18,7 @@ export default class AdminForthBaseConnector implements IAdminForthDataSourceCon client: any; get db() { - console.warn('.db is deprecated, use .client instead'); + afLogger.warn('.db is deprecated, use .client instead'); return this.client; } diff --git a/adminforth/dataConnectors/clickhouse.ts b/adminforth/dataConnectors/clickhouse.ts index 0e848c378..798682647 100644 --- a/adminforth/dataConnectors/clickhouse.ts +++ b/adminforth/dataConnectors/clickhouse.ts @@ -4,6 +4,7 @@ import dayjs from 'dayjs'; import { createClient } from '@clickhouse/client' import { AdminForthDataTypes, AdminForthFilterOperators, AdminForthSortDirections } from '../types/Common.js'; +import { afLogger } from '../modules/logger.js'; class ClickhouseConnector extends AdminForthBaseConnector implements IAdminForthDataSourceConnector { @@ -95,7 +96,7 @@ class ClickhouseConnector extends AdminForthBaseConnector implements IAdminForth }); rows = await q.json(); } catch (e) { - console.error(` 🛑Error connecting to datasource URL ${this.url}:`, e); + afLogger.error(` 🛑Error connecting to datasource URL ${this.url}: ${e}`); return null; } @@ -169,7 +170,7 @@ class ClickhouseConnector extends AdminForthBaseConnector implements IAdminForth return {'error': `Failed to parse JSON: ${e.message}`} } } else { - console.error(`AdminForth: JSON field is not a string but ${field._underlineType}, this is not supported yet`); + afLogger.error(`AdminForth: JSON field is not a string but ${field._underlineType}, this is not supported yet`); } } return value; @@ -197,7 +198,7 @@ class ClickhouseConnector extends AdminForthBaseConnector implements IAdminForth if (field._underlineType.startsWith('String') || field._underlineType.startsWith('FixedString')) { return JSON.stringify(value); } else { - console.error(`AdminForth: JSON field is not a string/text but ${field._underlineType}, this is not supported yet`); + afLogger.error(`AdminForth: JSON field is not a string/text but ${field._underlineType}, this is not supported yet`); } } diff --git a/adminforth/dataConnectors/mongo.ts b/adminforth/dataConnectors/mongo.ts index 82b4913bb..94487e26a 100644 --- a/adminforth/dataConnectors/mongo.ts +++ b/adminforth/dataConnectors/mongo.ts @@ -262,7 +262,7 @@ class MongoConnector extends AdminForthBaseConnector implements IAdminForthDataS // explicitly ignore raw SQL filters for MongoDB if ((filter as IAdminForthSingleFilter).insecureRawSQL !== undefined) { - console.warn('⚠️ Ignoring insecureRawSQL filter for MongoDB:', (filter as IAdminForthSingleFilter).insecureRawSQL); + afLogger.warn(`⚠️ Ignoring insecureRawSQL filter for MongoDB:, ${(filter as IAdminForthSingleFilter).insecureRawSQL}`); return {}; } diff --git a/adminforth/dataConnectors/mysql.ts b/adminforth/dataConnectors/mysql.ts index 490c9c9d6..ed97a8563 100644 --- a/adminforth/dataConnectors/mysql.ts +++ b/adminforth/dataConnectors/mysql.ts @@ -3,7 +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'; +import { dbLogger, afLogger } from '../modules/logger.js'; class MysqlConnector extends AdminForthBaseConnector implements IAdminForthDataSourceConnector { @@ -16,7 +16,7 @@ class MysqlConnector extends AdminForthBaseConnector implements IAdminForthDataS queueLimit: 0 }); } catch (e) { - console.error(`Failed to connect to MySQL: ${e}`); + afLogger.error(`Failed to connect to MySQL: ${e}`); } } @@ -176,8 +176,8 @@ class MysqlConnector extends AdminForthBaseConnector implements IAdminForthDataS } else if (typeof value === 'object') { return value; } else { - console.error('JSON field value is not string or object, but has type:', typeof value); - console.error('Field:', field); + afLogger.error(`JSON field value is not string or object, but has type: ${typeof value}`); + afLogger.error(`Field:, ${field}`); return {} } } diff --git a/adminforth/dataConnectors/postgres.ts b/adminforth/dataConnectors/postgres.ts index 89adf7271..639a29bc3 100644 --- a/adminforth/dataConnectors/postgres.ts +++ b/adminforth/dataConnectors/postgres.ts @@ -23,7 +23,7 @@ class PostgresConnector extends AdminForthBaseConnector implements IAdminForthDa this.setupClient(url); }); } catch (e) { - console.error(`Failed to connect to Postgres ${e}`); + afLogger.error(`Failed to connect to Postgres ${e}`); } } @@ -200,8 +200,8 @@ class PostgresConnector extends AdminForthBaseConnector implements IAdminForthDa } else if (typeof value == 'object') { return value; } else { - console.error('JSON field value is not string or object, but has type:', typeof value); - console.error('Field:', field); + afLogger.error(`JSON field value is not string or object, but has type: ${typeof value}`); + afLogger.error(`Field:, ${field}`); return {} } } diff --git a/adminforth/dataConnectors/sqlite.ts b/adminforth/dataConnectors/sqlite.ts index 7331a7ecf..5538e23fc 100644 --- a/adminforth/dataConnectors/sqlite.ts +++ b/adminforth/dataConnectors/sqlite.ts @@ -3,7 +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'; +import { dbLogger, afLogger } from '../modules/logger.js'; class SQLiteConnector extends AdminForthBaseConnector implements IAdminForthDataSourceConnector { @@ -123,7 +123,7 @@ class SQLiteConnector extends AdminForthBaseConnector implements IAdminForthData return {'error': `Failed to parse JSON: ${e.message}`} } } else { - console.error(`AdminForth: JSON field is not a string/text but ${field._underlineType}, this is not supported yet`); + afLogger.error(`AdminForth: JSON field is not a string/text but ${field._underlineType}, this is not supported yet`); } } @@ -157,7 +157,7 @@ class SQLiteConnector extends AdminForthBaseConnector implements IAdminForthData if (field._underlineType == 'text' || field._underlineType == 'varchar') { return JSON.stringify(value); } else { - console.error(`AdminForth: JSON field is not a string/text but ${field._underlineType}, this is not supported yet`); + afLogger.error(`AdminForth: JSON field is not a string/text but ${field._underlineType}, this is not supported yet`); } } diff --git a/adminforth/index.ts b/adminforth/index.ts index a08c80537..a06d30556 100644 --- a/adminforth/index.ts +++ b/adminforth/index.ts @@ -384,7 +384,7 @@ class AdminForth implements IAdminForth { try { await this.connectors[dataSourceId].setupClient(this.config.dataSources.find((ds) => ds.id === dataSourceId).url); } catch (e) { - console.error(`Error while connecting to datasource '${dataSourceId}':`, e); + afLogger.error(`Error while connecting to datasource '${dataSourceId}': ${e}`); } })); @@ -399,13 +399,13 @@ class AdminForth implements IAdminForth { try { fieldTypes = await this.connectors[res.dataSource].discoverFields(res); } catch (e) { - console.error(`Error discovering fields for resource '${res.table}' (In resource '${res.resourceId}')`, e); + afLogger.error(`Error discovering fields for resource '${res.table}' (In resource '${res.resourceId}') ${e}`); } if (fieldTypes !== null && !Object.keys(fieldTypes).length) { throw new Error(`Table '${res.table}' (In resource '${res.resourceId}') has no fields or does not exist`); } if (fieldTypes === null) { - console.error(`⛔ DataSource ${res.dataSource} was not able to perform field discovery. It will not work properly`); + afLogger.error(`⛔ DataSource ${res.dataSource} was not able to perform field discovery. It will not work properly`); if (process.env.NODE_ENV === 'production') { process.exit(1); } @@ -458,7 +458,7 @@ class AdminForth implements IAdminForth { const tables = await connector.getAllTables(); results[dataSourceId] = tables; } catch (err) { - console.error(`Error getting tables for dataSource ${dataSourceId}:`, err); + afLogger.error(`Error getting tables for dataSource ${dataSourceId}: ${err}`); results[dataSourceId] = []; } } else { @@ -489,7 +489,7 @@ class AdminForth implements IAdminForth { isUUID: isProbablyUUIDColumn(column), })); } catch (err) { - console.error(`Error getting columns for table ${tableName} in dataSource ${dataSourceId}:`, err); + afLogger.error(`Error getting columns for table ${tableName} in dataSource ${dataSourceId}: ${err}`); results[dataSourceId] = []; } } else { @@ -631,7 +631,7 @@ class AdminForth implements IAdminForth { } if (record) { - console.warn(`updateResourceRecord function received 'record' param which is deprecated and will be removed in future version, please use 'updates' instead.`); + afLogger.warn(`updateResourceRecord function received 'record' param which is deprecated and will be removed in future version, please use 'updates' instead.`); } // remove editReadonly columns from record diff --git a/adminforth/modules/codeInjector.ts b/adminforth/modules/codeInjector.ts index 7f7c3c2dc..b67b6bead 100644 --- a/adminforth/modules/codeInjector.ts +++ b/adminforth/modules/codeInjector.ts @@ -965,8 +965,8 @@ class CodeInjector implements ICodeInjector { } }); devServer.stderr.on('data', (data) => { - console.error(`[AdminForth SPA ERROR]:`); - afLogger.trace(data.toString()); + afLogger.error(`[AdminForth SPA ERROR]:`); + afLogger.error(data.toString()); }); } diff --git a/adminforth/modules/configValidator.ts b/adminforth/modules/configValidator.ts index 8aa830ebc..1d60c3ee8 100644 --- a/adminforth/modules/configValidator.ts +++ b/adminforth/modules/configValidator.ts @@ -29,6 +29,7 @@ import { } from "../types/Common.js"; import AdminForth from "adminforth"; import { AdminForthConfigMenuItem } from "adminforth"; +import { afLogger } from "./logger.js"; export default class ConfigValidator implements IConfigValidator { @@ -1211,7 +1212,7 @@ export default class ConfigValidator implements IConfigValidator { } if (warnings.length > 0) { - console.warn(`AdminForth config warnings: ${warnings.join(', ')}`); + afLogger.warn(`AdminForth config warnings: ${warnings.join(', ')}`); } //add ids for onSelectedAllActions for each resource diff --git a/adminforth/modules/socketBroker.ts b/adminforth/modules/socketBroker.ts index 758168129..a47481322 100644 --- a/adminforth/modules/socketBroker.ts +++ b/adminforth/modules/socketBroker.ts @@ -73,7 +73,7 @@ export default class SocketBroker implements IWebSocketBroker { try { authResult = await this.adminforth.config.auth.websocketTopicAuth(data.topic, client.adminUser); } catch (e) { - console.error('Error in websocketTopicAuth, assuming connection not allowed', e); + afLogger.error('Error in websocketTopicAuth, assuming connection not allowed', e); } if (!authResult) { client.send(JSON.stringify({ type: 'error', message: 'Unauthorized' })); @@ -94,7 +94,7 @@ export default class SocketBroker implements IWebSocketBroker { try { await this.adminforth.config.auth.websocketSubscribed(data.topic, client.adminUser); } catch (e) { - console.error(`Error in websocketSubscribed for topic ${data.topic}`, e); + afLogger.error(`Error in websocketSubscribed for topic ${data.topic}`, e); } })(); // run in background } diff --git a/adminforth/servers/express.ts b/adminforth/servers/express.ts index bd3b29dac..d88f1f36a 100644 --- a/adminforth/servers/express.ts +++ b/adminforth/servers/express.ts @@ -200,7 +200,7 @@ class ExpressServer implements IExpressHttpServer { }) ); } catch (e) { - console.error('Failed to handle WS connection', e); + afLogger.error(`Failed to handle WS connection ${e}`); } }); @@ -244,7 +244,7 @@ class ExpressServer implements IExpressHttpServer { // check if multiple adminforth_jwt providerd and show warning const jwts = cookies.filter(({key}) => key === `adminforth_${brandSlug}_jwt`); if (jwts.length > 1) { - console.error('Multiple adminforth_jwt cookies provided'); + afLogger.error('Multiple adminforth_jwt cookies provided'); } const jwt = jwts[0]?.value; @@ -260,7 +260,7 @@ class ExpressServer implements IExpressHttpServer { // this might happen if e.g. database intialization in progress. // so we can't answer with 401 (would logout user) // reproduced during usage of listRowsAutoRefreshSeconds - console.error(e.stack); + afLogger.error(e.stack); res.status(500).send('Failed to verify JWT token - something went wrong'); return; } @@ -313,7 +313,7 @@ class ExpressServer implements IExpressHttpServer { try { body = JSON.parse(body); } catch (e) { - console.error('Failed to parse body', e); + afLogger.error('Failed to parse body', e); res.status(400).send('Invalid JSON body'); } } @@ -355,9 +355,9 @@ class ExpressServer implements IExpressHttpServer { try { output = await handler(input); } catch (e) { - console.error('Error in handler', e); + afLogger.error(`Error in handler ${e}`); // print full stack trace - console.error(e.stack); + afLogger.error(e.stack); res.status(500).send('Internal server error'); return; } From 2c0f744d96d054bb56a9cc7e5c3fe0b16a4b8b7b Mon Sep 17 00:00:00 2001 From: yaroslav8765 Date: Mon, 12 Jan 2026 11:03:49 +0200 Subject: [PATCH 09/13] fix: rebuild --- adminforth/modules/codeInjector.ts | 2 +- adminforth/modules/socketBroker.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/adminforth/modules/codeInjector.ts b/adminforth/modules/codeInjector.ts index b67b6bead..b40d10322 100644 --- a/adminforth/modules/codeInjector.ts +++ b/adminforth/modules/codeInjector.ts @@ -930,7 +930,7 @@ class CodeInjector implements ICodeInjector { const command = 'run dev'; afLogger.info(`⚙️ spawn: npm ${command}...`); if (process.env.VITE_ADMINFORTH_PUBLIC_PATH) { - afLogger.info('⚠️ 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/socketBroker.ts b/adminforth/modules/socketBroker.ts index a47481322..8e68f97b4 100644 --- a/adminforth/modules/socketBroker.ts +++ b/adminforth/modules/socketBroker.ts @@ -73,7 +73,7 @@ export default class SocketBroker implements IWebSocketBroker { try { authResult = await this.adminforth.config.auth.websocketTopicAuth(data.topic, client.adminUser); } catch (e) { - afLogger.error('Error in websocketTopicAuth, assuming connection not allowed', e); + afLogger.error(`Error in websocketTopicAuth, assuming connection not allowed ${e}`); } if (!authResult) { client.send(JSON.stringify({ type: 'error', message: 'Unauthorized' })); @@ -94,7 +94,7 @@ export default class SocketBroker implements IWebSocketBroker { try { await this.adminforth.config.auth.websocketSubscribed(data.topic, client.adminUser); } catch (e) { - afLogger.error(`Error in websocketSubscribed for topic ${data.topic}`, e); + afLogger.error(`Error in websocketSubscribed for topic ${data.topic}, ${e}`); } })(); // run in background } From d5d641bd1e8d3e072ecac071797c7fc5a762ec0c Mon Sep 17 00:00:00 2001 From: yaroslav8765 Date: Mon, 12 Jan 2026 11:04:53 +0200 Subject: [PATCH 10/13] fix: rebuild --- adminforth/servers/express.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adminforth/servers/express.ts b/adminforth/servers/express.ts index d88f1f36a..7c321084e 100644 --- a/adminforth/servers/express.ts +++ b/adminforth/servers/express.ts @@ -313,7 +313,7 @@ class ExpressServer implements IExpressHttpServer { try { body = JSON.parse(body); } catch (e) { - afLogger.error('Failed to parse body', e); + afLogger.error(`Failed to parse body, ${e}`); res.status(400).send('Invalid JSON body'); } } From 5419fa9adf8874d6a1f63c846124545c7fed8431 Mon Sep 17 00:00:00 2001 From: yaroslav8765 Date: Mon, 12 Jan 2026 11:14:12 +0200 Subject: [PATCH 11/13] chore: resolve copilot review comments --- adminforth/commands/callTsProxy.js | 2 +- adminforth/commands/createApp/templates/adminuser.ts.hbs | 3 ++- adminforth/commands/createCustomComponent/fileGenerator.js | 2 +- adminforth/commands/postinstall.js | 2 +- adminforth/index.ts | 2 +- adminforth/modules/logger.ts | 1 - 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/adminforth/commands/callTsProxy.js b/adminforth/commands/callTsProxy.js index 8eeb5d292..40b0d007b 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) => { - afLogger.log(...log); + afLogger.info(...log); }); } diff --git a/adminforth/commands/createApp/templates/adminuser.ts.hbs b/adminforth/commands/createApp/templates/adminuser.ts.hbs index 494c7577f..c56ab2854 100644 --- a/adminforth/commands/createApp/templates/adminuser.ts.hbs +++ b/adminforth/commands/createApp/templates/adminuser.ts.hbs @@ -1,5 +1,6 @@ import AdminForth, { AdminForthDataTypes } from 'adminforth'; -import type { AdminForthResourceInput, AdminForthResource, AdminUser, logger } from 'adminforth'; +import type { AdminForthResourceInput, AdminForthResource, AdminUser } from 'adminforth'; +import { logger } from 'adminforth'; import { randomUUID } from 'crypto'; async function allowedForSuperAdmin({ adminUser }: { adminUser: AdminUser }): Promise { diff --git a/adminforth/commands/createCustomComponent/fileGenerator.js b/adminforth/commands/createCustomComponent/fileGenerator.js index 896c49516..54c9c43ac 100644 --- a/adminforth/commands/createCustomComponent/fileGenerator.js +++ b/adminforth/commands/createCustomComponent/fileGenerator.js @@ -125,7 +125,7 @@ export async function generateLoginOrGlobalComponentFile(componentFileName, inje try { await fs.mkdir(customDirPath, { recursive: true }); - afLogger.warn(chalk.dim(`Ensured custom directory exists: ${customDirPath}`)); + afLogger.info(chalk.dim(`Ensured custom directory exists: ${customDirPath}`)); const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); diff --git a/adminforth/commands/postinstall.js b/adminforth/commands/postinstall.js index bc7fa6075..b838955d9 100644 --- a/adminforth/commands/postinstall.js +++ b/adminforth/commands/postinstall.js @@ -13,5 +13,5 @@ if (fs.existsSync(spaPath)){ afLogger.info('Installed spa dependencies'); } else { afLogger.warn('SPA dependencies not found'); - afLogger.info('current directory', import.meta.dirname); + afLogger.warn(`current directory: ${import.meta.dirname}`); } \ No newline at end of file diff --git a/adminforth/index.ts b/adminforth/index.ts index a06d30556..225e04c18 100644 --- a/adminforth/index.ts +++ b/adminforth/index.ts @@ -550,7 +550,7 @@ class AdminForth implements IAdminForth { // execute hook if needed for (const hook of listify(resource.hooks?.create?.beforeSave)) { - console.debug('🪲 Hook beforeSave', hook); + afLogger.debug(`🪲 Hook beforeSave ${hook}`); const resp = await hook({ resource, record, diff --git a/adminforth/modules/logger.ts b/adminforth/modules/logger.ts index 06f3a8ece..cf6a8d405 100644 --- a/adminforth/modules/logger.ts +++ b/adminforth/modules/logger.ts @@ -1,5 +1,4 @@ import pino from 'pino'; -import { PinoPretty } from "pino-pretty"; const baseLogger = pino({ transport: { From 84a02a15bb783f861f3d886233ea9efe15a97280 Mon Sep 17 00:00:00 2001 From: yaroslav8765 Date: Mon, 12 Jan 2026 11:28:29 +0200 Subject: [PATCH 12/13] chore: resolve copilot review comments[2] --- adminforth/commands/callTsProxy.js | 2 +- adminforth/commands/createApp/utils.js | 2 +- adminforth/commands/createCustomComponent/configLoader.js | 2 +- adminforth/commands/createCustomComponent/configUpdater.js | 2 +- adminforth/commands/createCustomComponent/fileGenerator.js | 2 +- adminforth/commands/createCustomComponent/main.js | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/adminforth/commands/callTsProxy.js b/adminforth/commands/callTsProxy.js index 40b0d007b..463c01840 100644 --- a/adminforth/commands/callTsProxy.js +++ b/adminforth/commands/callTsProxy.js @@ -4,7 +4,7 @@ import path from "path"; import fs from "fs"; import chalk from "chalk"; import dotenv from "dotenv"; -import { afLogger } from './modules/logger.js'; +import { afLogger } from '../modules/logger.js'; const currentFilePath = import.meta.url; const currentFileFolder = path.dirname(currentFilePath).replace("file:", ""); diff --git a/adminforth/commands/createApp/utils.js b/adminforth/commands/createApp/utils.js index 44bd751fc..f6fb7d85c 100644 --- a/adminforth/commands/createApp/utils.js +++ b/adminforth/commands/createApp/utils.js @@ -12,7 +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'; +import { afLogger } from '../../modules/logger.js'; const execAsync = promisify(exec); diff --git a/adminforth/commands/createCustomComponent/configLoader.js b/adminforth/commands/createCustomComponent/configLoader.js index 5f4c0ad10..31560c8f6 100644 --- a/adminforth/commands/createCustomComponent/configLoader.js +++ b/adminforth/commands/createCustomComponent/configLoader.js @@ -3,7 +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'; +import { afLogger } from '../../modules/logger.js'; dotenv.config({ path: '.env.local', override: true }); dotenv.config({ path: '.env', override: true }); diff --git a/adminforth/commands/createCustomComponent/configUpdater.js b/adminforth/commands/createCustomComponent/configUpdater.js index e64c04561..49b0a1ad4 100644 --- a/adminforth/commands/createCustomComponent/configUpdater.js +++ b/adminforth/commands/createCustomComponent/configUpdater.js @@ -3,7 +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'; +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 diff --git a/adminforth/commands/createCustomComponent/fileGenerator.js b/adminforth/commands/createCustomComponent/fileGenerator.js index 54c9c43ac..befc6a0eb 100644 --- a/adminforth/commands/createCustomComponent/fileGenerator.js +++ b/adminforth/commands/createCustomComponent/fileGenerator.js @@ -4,7 +4,7 @@ import path from 'path'; import chalk from 'chalk'; import Handlebars from 'handlebars'; import { fileURLToPath } from 'url'; -import { afLogger } from '../modules/logger.js'; +import { afLogger } from '../../modules/logger.js'; async function renderHBSTemplate(templatePath, data) { try { diff --git a/adminforth/commands/createCustomComponent/main.js b/adminforth/commands/createCustomComponent/main.js index 1da3415ef..01fb1309e 100644 --- a/adminforth/commands/createCustomComponent/main.js +++ b/adminforth/commands/createCustomComponent/main.js @@ -4,7 +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'; +import { afLogger } from '../../modules/logger.js'; function sanitizeLabel(input){ return input From a66db2a95dfbb7366bbef01f4d2971f299d003b9 Mon Sep 17 00:00:00 2001 From: yaroslav8765 Date: Mon, 12 Jan 2026 11:36:52 +0200 Subject: [PATCH 13/13] chore: revert afLogger updates for the commands --- adminforth/commands/bundle.js | 5 +- adminforth/commands/callTsProxy.js | 19 ++--- .../createApp/templates/adminuser.ts.hbs | 3 +- .../commands/createApp/templates/index.ts.hbs | 6 +- adminforth/commands/createApp/utils.js | 8 +- .../createCustomComponent/configLoader.js | 7 +- .../createCustomComponent/configUpdater.js | 85 +++++++++---------- .../createCustomComponent/fileGenerator.js | 29 +++---- .../commands/createCustomComponent/main.js | 6 +- .../templates/customCrud/saveButton.vue.hbs | 28 ------ adminforth/commands/postinstall.js | 10 +-- adminforth/commands/proxy.ts | 5 +- adminforth/commands/utils.js | 5 +- 13 files changed, 87 insertions(+), 129 deletions(-) delete mode 100644 adminforth/commands/createCustomComponent/templates/customCrud/saveButton.vue.hbs diff --git a/adminforth/commands/bundle.js b/adminforth/commands/bundle.js index 9bb4d622b..42b882bef 100644 --- a/adminforth/commands/bundle.js +++ b/adminforth/commands/bundle.js @@ -1,9 +1,8 @@ import { callTsProxy, findAdminInstance } from "./callTsProxy.js"; -import { afLogger } from '../modules/logger.js'; async function bundle() { - afLogger.info("Bundling admin SPA..."); + console.log("Bundling admin SPA..."); const instance = await findAdminInstance(); @@ -17,7 +16,7 @@ async function bundle() { `); } catch (e) { - afLogger.error(`Running bundle failed`, e); + console.log(`Running budndle failed`, e); } } diff --git a/adminforth/commands/callTsProxy.js b/adminforth/commands/callTsProxy.js index 463c01840..55c37db09 100644 --- a/adminforth/commands/callTsProxy.js +++ b/adminforth/commands/callTsProxy.js @@ -4,7 +4,6 @@ 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:", ""); @@ -21,7 +20,7 @@ export function callTsProxy(tsCode, silent=false) { dotenv.config({ path: envPath, override: true }); } - afLogger.trace("🌐 Calling tsproxy with code:", path.join(currentFileFolder, "proxy.ts")); + process.env.HEAVY_DEBUG && console.log("🌐 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, @@ -43,7 +42,7 @@ export function callTsProxy(tsCode, silent=false) { const parsed = JSON.parse(stdout); if (!silent) { parsed.capturedLogs.forEach((log) => { - afLogger.info(...log); + console.log(...log); }); } @@ -55,19 +54,19 @@ export function callTsProxy(tsCode, silent=false) { reject(new Error("Invalid JSON from tsproxy: " + stdout)); } } else { - afLogger.error(`tsproxy exited with non-0, this should never happen, stdout: ${stdout}, stderr: ${stderr}`); + console.error(`tsproxy exited with non-0, this should never happen, stdout: ${stdout}, stderr: ${stderr}`); reject(new Error(stderr)); } }); - afLogger.trace("🪲 Writing to tsproxy stdin...\n'''", tsCode, "'''"); + process.env.HEAVY_DEBUG && console.log("🪲 Writing to tsproxy stdin...\n'''", tsCode, "'''"); child.stdin.write(tsCode); child.stdin.end(); }); } export async function findAdminInstance() { - afLogger.trace("🌐 Finding admin instance..."); + process.env.HEAVY_DEBUG && console.log("🌐 Finding admin instance..."); const currentDirectory = process.cwd(); let files = fs.readdirSync(currentDirectory); @@ -84,7 +83,7 @@ export async function findAdminInstance() { for (const file of files) { if (file.endsWith(".ts")) { const fileNoTs = file.replace(/\.ts$/, ""); - afLogger.trace(`🪲 Trying bundleing ${file}...`); + process.env.HEAVY_DEBUG && console.log(`🪲 Trying bundleing ${file}...`); try { const res = await callTsProxy(` import { admin } from './${fileNoTs}.js'; @@ -102,10 +101,10 @@ export async function findAdminInstance() { // and show the error so user can fix it const fileContent = fs.readFileSync(file, "utf-8"); if (fileContent.includes("export const admin")) { - afLogger.error(`Error running ${file}: ${e}`); + console.error(chalk.red(`Error running ${file}:`, e)); process.exit(1); } - afLogger.trace(`🪲 File ${file} failed`, e); + process.env.HEAVY_DEBUG && console.log(`🪲 File ${file} failed`, e); } } } @@ -131,4 +130,4 @@ export async function findAdminInstance() { // function exec() { // return admin.doX(); // } -// `).then(afLogger.info).catch(afLogger.error); +// `).then(console.log).catch(console.error); diff --git a/adminforth/commands/createApp/templates/adminuser.ts.hbs b/adminforth/commands/createApp/templates/adminuser.ts.hbs index c56ab2854..0eb77905f 100644 --- a/adminforth/commands/createApp/templates/adminuser.ts.hbs +++ b/adminforth/commands/createApp/templates/adminuser.ts.hbs @@ -1,6 +1,5 @@ import AdminForth, { AdminForthDataTypes } from 'adminforth'; import type { AdminForthResourceInput, AdminForthResource, AdminUser } from 'adminforth'; -import { logger } from 'adminforth'; import { randomUUID } from 'crypto'; async function allowedForSuperAdmin({ adminUser }: { adminUser: AdminUser }): Promise { @@ -95,7 +94,7 @@ export default { }, edit: { beforeSave: async ({ oldRecord, updates, adminUser, resource }: { oldRecord: any, updates: any, adminUser: AdminUser, resource: AdminForthResource }) => { - logger.info('Updating user', updates); + console.log('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 38696c2ab..ae7722b08 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, logger } from 'adminforth'; +import { Filters } 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(() => { - logger.info('Bundling AdminForth SPA done.'); + console.log('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, () => { - logger.info(`\n⚡ AdminForth is available at http://localhost:${port}${ADMIN_BASE_URL}\n`); + console.log(`\n⚡ AdminForth is available at http://localhost:${port}${ADMIN_BASE_URL}\n`); }); } diff --git a/adminforth/commands/createApp/utils.js b/adminforth/commands/createApp/utils.js index f6fb7d85c..6e13a84f1 100644 --- a/adminforth/commands/createApp/utils.js +++ b/adminforth/commands/createApp/utils.js @@ -12,7 +12,6 @@ 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); @@ -336,6 +335,7 @@ 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) => { - afLogger.info(chalk.green(`✅ Successfully created your new Adminforth project in ${ctx.projectDir}!\n`)); - afLogger.info(generateFinalInstructions(ctx.skipPrismaSetup, options)); - afLogger.info('\n\n'); + console.log(chalk.green(`✅ Successfully created your new Adminforth project in ${ctx.projectDir}!\n`)); + console.log(generateFinalInstructions(ctx.skipPrismaSetup, options)); + console.log('\n\n'); } } ], diff --git a/adminforth/commands/createCustomComponent/configLoader.js b/adminforth/commands/createCustomComponent/configLoader.js index 31560c8f6..d7029d783 100644 --- a/adminforth/commands/createCustomComponent/configLoader.js +++ b/adminforth/commands/createCustomComponent/configLoader.js @@ -3,7 +3,6 @@ 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 }); @@ -60,12 +59,12 @@ export async function loadAdminForthConfig() { } - afLogger.info(chalk.dim(`Loaded configuration from ${configPath}`)); + console.log(chalk.dim(`Loaded configuration from ${configPath}`)); return config; } catch (error) { - afLogger.error(chalk.red(`\nError loading or parsing configuration file: ${configPath}, error: ${error}`)); - afLogger.error(error); + console.error(chalk.red(`\nError loading or parsing configuration file: ${configPath}, error: ${error}`)); + console.error(error); process.exit(1); } } diff --git a/adminforth/commands/createCustomComponent/configUpdater.js b/adminforth/commands/createCustomComponent/configUpdater.js index 49b0a1ad4..2ed43e1ba 100644 --- a/adminforth/commands/createCustomComponent/configUpdater.js +++ b/adminforth/commands/createCustomComponent/configUpdater.js @@ -3,7 +3,6 @@ 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 @@ -12,7 +11,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'); - afLogger.info(chalk.dim(`Scanning for resource files in: ${resourcesDir}`)); + console.log(chalk.dim(`Scanning for resource files in: ${resourcesDir}`)); let tsFiles = []; try { @@ -30,7 +29,7 @@ async function findResourceFilePath(resourceId) { for (const file of tsFiles) { const filePath = path.resolve(resourcesDir, file); - afLogger.info(chalk.dim(`Attempting to process file: ${file}`)); + console.log(chalk.dim(`Attempting to process file: ${file}`)); try { const content = await fs.readFile(filePath, 'utf-8'); const ast = recast.parse(content, { @@ -80,7 +79,7 @@ async function findResourceFilePath(resourceId) { ); if (resourceIdProp) { foundResourceId = resourceIdProp.value.value; // Get the string value - afLogger.info(chalk.dim(` Extracted resourceId '${foundResourceId}' from ${file}`)); + console.log(chalk.dim(` Extracted resourceId '${foundResourceId}' from ${file}`)); this.abort(); // Stop traversal for this file once found } } @@ -88,17 +87,17 @@ async function findResourceFilePath(resourceId) { } }); - afLogger.info(chalk.dim(` Finished processing ${file}. Found resourceId: ${foundResourceId || 'null'}`)); + console.log(chalk.dim(` Finished processing ${file}. Found resourceId: ${foundResourceId || 'null'}`)); if (foundResourceId === resourceId) { - afLogger.info(chalk.dim(` Match found! Returning path: ${filePath}`)); + console.log(chalk.dim(` Match found! Returning path: ${filePath}`)); return filePath; } } catch (parseError) { if (parseError.message.includes('require is not defined')) { - afLogger.error(chalk.red(`❌ Internal Error: Failed to load Recast parser in ESM context for ${file}.`)); + console.error(chalk.red(`❌ Internal Error: Failed to load Recast parser in ESM context for ${file}.`)); } else { - afLogger.warn(chalk.yellow(`⚠️ Warning: Could not process file ${file}. Skipping. Error: ${parseError.message}`)); + console.warn(chalk.yellow(`⚠️ Warning: Could not process file ${file}. Skipping. Error: ${parseError.message}`)); } } } @@ -109,15 +108,15 @@ async function findResourceFilePath(resourceId) { export async function updateResourceConfig(resourceId, columnName, fieldType, componentPathForConfig) { const filePath = await findResourceFilePath(resourceId); - afLogger.info(chalk.dim(`Attempting to update resource config: ${filePath}`)); + console.log(chalk.dim(`Attempting to update resource config: ${filePath}`)); let content; let injectionLine = null; try { content = await fs.readFile(filePath, 'utf-8'); } catch (error) { - afLogger.error(chalk.red(`❌ Error reading resource file: ${filePath}`)); - afLogger.error(error); + console.error(chalk.red(`❌ Error reading resource file: ${filePath}`)); + console.error(error); throw new Error(`Could not read resource file ${filePath}.`); } @@ -199,10 +198,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); - afLogger.info(chalk.dim(`Added 'components' object to column '${columnName}'.`)); + console.log(chalk.dim(`Added 'components' object to column '${columnName}'.`)); } else if (!n.ObjectExpression.check(componentsProperty.value)) { - afLogger.warn(chalk.yellow(`Warning: 'components' property in column '${columnName}' is not an object. Skipping update.`)); + console.warn(chalk.yellow(`Warning: 'components' property in column '${columnName}' is not an object. Skipping update.`)); return false; } @@ -216,7 +215,7 @@ export async function updateResourceConfig(resourceId, columnName, fieldType, co if (fieldTypeProperty) { injectionLine = fieldTypeProperty.loc?.start.line ?? null; fieldTypeProperty.value = newComponentValue; - afLogger.info(chalk.dim(`Updated '${fieldType}' component path in column '${columnName}'.`)); + console.log(chalk.dim(`Updated '${fieldType}' component path in column '${columnName}'.`)); } else { fieldTypeProperty = b.objectProperty(b.identifier(fieldType), newComponentValue); componentsObject.properties.push(fieldTypeProperty); @@ -224,7 +223,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; - afLogger.info(chalk.dim(`Added '${fieldType}' component path to column '${columnName}'.`)); + console.log(chalk.dim(`Added '${fieldType}' component path to column '${columnName}'.`)); } updateApplied = true; @@ -240,7 +239,7 @@ export async function updateResourceConfig(resourceId, columnName, fieldType, co const outputCode = recast.print(ast).code; await fs.writeFile(filePath, outputCode, 'utf-8'); - afLogger.info( + console.log( chalk.green( `✅ Successfully updated CRUD injection in resource file: ${filePath}` + (injectionLine !== null ? `:${injectionLine}` : '') @@ -256,7 +255,7 @@ export async function updateResourceConfig(resourceId, columnName, fieldType, co export async function injectLoginComponent(indexFilePath, componentPath, injectionType) { - afLogger.info(chalk.dim(`Reading file: ${indexFilePath}`)); + console.log(chalk.dim(`Reading file: ${indexFilePath}`)); const content = await fs.readFile(indexFilePath, 'utf-8'); const ast = recast.parse(content, { parser: typescriptParser, @@ -284,7 +283,7 @@ export async function injectLoginComponent(indexFilePath, componentPath, injecti const newObj = b.objectExpression([]); prop = b.objectProperty(b.identifier(name), newObj); obj.properties.push(prop); - afLogger.info(chalk.dim(`Added missing '${name}' property.`)); + console.log(chalk.dim(`Added missing '${name}' property.`)); } return prop.value; }; @@ -311,9 +310,9 @@ export async function injectLoginComponent(indexFilePath, componentPath, injecti b.stringLiteral(currentVal.value), b.stringLiteral(componentPath), ]); - afLogger.info(chalk.dim(`Converted '${targetProperty}' to array with existing + new path.`)); + console.log(chalk.dim(`Converted '${targetProperty}' to array with existing + new path.`)); } else { - afLogger.info(chalk.dim(`Component path already present as string. Skipping.`)); + console.log(chalk.dim(`Component path already present as string. Skipping.`)); } } else if (n.ArrayExpression.check(currentVal)) { const exists = currentVal.elements.some( @@ -321,12 +320,12 @@ export async function injectLoginComponent(indexFilePath, componentPath, injecti ); if (!exists) { currentVal.elements.push(b.stringLiteral(componentPath)); - afLogger.info(chalk.dim(`Appended new component path to existing '${targetProperty}' array.`)); + console.log(chalk.dim(`Appended new component path to existing '${targetProperty}' array.`)); } else { - afLogger.info(chalk.dim(`Component path already present in array. Skipping.`)); + console.log(chalk.dim(`Component path already present in array. Skipping.`)); } } else { - afLogger.warn(chalk.yellow(`⚠️ '${targetProperty}' is not a string or array. Skipping.`)); + console.warn(chalk.yellow(`⚠️ '${targetProperty}' is not a string or array. Skipping.`)); return false; } } else { @@ -336,11 +335,11 @@ export async function injectLoginComponent(indexFilePath, componentPath, injecti ); if (newProperty.loc) { - afLogger.info(chalk.dim(`Adding '${targetProperty}' at line: ${newProperty.loc.start.line}`)); + console.log(chalk.dim(`Adding '${targetProperty}' at line: ${newProperty.loc.start.line}`)); } loginPageInjections.properties.push(newProperty); - afLogger.info(chalk.dim(`Added '${targetProperty}': ${componentPath}`)); + console.log(chalk.dim(`Added '${targetProperty}': ${componentPath}`)); } updated = true; @@ -356,7 +355,7 @@ export async function injectLoginComponent(indexFilePath, componentPath, injecti const outputCode = recast.print(ast).code; await fs.writeFile(indexFilePath, outputCode, 'utf-8'); - afLogger.info( + console.log( chalk.green( `✅ Successfully updated login ${targetProperty} injection in: ${indexFilePath}` + (injectionLine !== null ? `:${injectionLine}` : '') @@ -366,7 +365,7 @@ export async function injectLoginComponent(indexFilePath, componentPath, injecti export async function injectGlobalComponent(indexFilePath, injectionType, componentPath) { - afLogger.info(chalk.dim(`Reading file: ${indexFilePath}`)); + console.log(chalk.dim(`Reading file: ${indexFilePath}`)); const content = await fs.readFile(indexFilePath, 'utf-8'); const ast = recast.parse(content, { parser: typescriptParser, @@ -374,7 +373,7 @@ export async function injectGlobalComponent(indexFilePath, injectionType, compon let updated = false; let injectionLine = null; - afLogger.info(JSON.stringify(injectionType)); + console.log(JSON.stringify(injectionType)); recast.visit(ast, { visitNewExpression(path) { if ( @@ -393,7 +392,7 @@ export async function injectGlobalComponent(indexFilePath, injectionType, compon const customizationObj = b.objectExpression([]); customizationProp = b.objectProperty(b.identifier('customization'), customizationObj); configObject.properties.push(customizationProp); - afLogger.info(chalk.dim(`Added missing 'customization' property.`)); + console.log(chalk.dim(`Added missing 'customization' property.`)); } const customizationValue = customizationProp.value; @@ -407,12 +406,12 @@ export async function injectGlobalComponent(indexFilePath, injectionType, compon const injectionsObj = b.objectExpression([]); globalInjections = b.objectProperty(b.identifier('globalInjections'), injectionsObj); customizationValue.properties.push(globalInjections); - afLogger.info(chalk.dim(`Added missing 'globalInjections'.`)); + console.log(chalk.dim(`Added missing 'globalInjections'.`)); } const injectionsValue = globalInjections.value; if (!n.ObjectExpression.check(injectionsValue)) return false; - afLogger.info(JSON.stringify(injectionType)); + console.log(JSON.stringify(injectionType)); let injectionProp = injectionsValue.properties.find( p => n.ObjectProperty.check(p) && n.Identifier.check(p.key) && p.key.name === injectionType ); @@ -421,13 +420,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)); - afLogger.info(chalk.dim(`Added '${componentPath}' to existing array in '${injectionType}'`)); + console.log(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) ]); - afLogger.info(chalk.dim(`Converted '${injectionType}' from string to array and added '${componentPath}'`)); + console.log(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.`); } @@ -438,7 +437,7 @@ export async function injectGlobalComponent(indexFilePath, injectionType, compon b.arrayExpression([b.stringLiteral(componentPath)]) ) ); - afLogger.info(chalk.dim(`Added new array for '${injectionType}' with '${componentPath}'`)); + console.log(chalk.dim(`Added new array for '${injectionType}' with '${componentPath}'`)); } updated = true; @@ -454,7 +453,7 @@ export async function injectGlobalComponent(indexFilePath, injectionType, compon const outputCode = recast.print(ast).code; await fs.writeFile(indexFilePath, outputCode, 'utf-8'); - afLogger.info( + console.log( chalk.green( `✅ Successfully updated CRUD injection in resource file: ${indexFilePath}` + (injectionLine !== null ? `:${injectionLine}` : '') @@ -464,14 +463,14 @@ export async function injectGlobalComponent(indexFilePath, injectionType, compon export async function updateCrudInjectionConfig(resourceId, crudType, injectionPosition, componentPathForConfig, isThin) { const filePath = await findResourceFilePath(resourceId); - afLogger.info(chalk.dim(`Attempting to update resource CRUD injection: ${filePath}`)); + console.log(chalk.dim(`Attempting to update resource CRUD injection: ${filePath}`)); let content; let injectionLine = null; try { content = await fs.readFile(filePath, 'utf-8'); } catch (error) { - afLogger.error(chalk.red(`❌ Error reading resource file: ${filePath}`)); + console.error(chalk.red(`❌ Error reading resource file: ${filePath}`)); throw new Error(`Could not read resource file ${filePath}.`); } @@ -565,21 +564,21 @@ export async function updateCrudInjectionConfig(resourceId, crudType, injectionP if (injectionProp) { if (n.ArrayExpression.check(injectionProp.value)) { injectionProp.value.elements.push(newInjectionObject); - afLogger.info(chalk.dim(`Appended new injection to array at '${injectionPosition}' for '${crudType}'.`)); + console.log(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]); - afLogger.info(chalk.dim(`Converted to array and added new injection at '${injectionPosition}' for '${crudType}'.`)); + console.log(chalk.dim(`Converted to array and added new injection at '${injectionPosition}' for '${crudType}'.`)); } else { injectionProp.value = b.arrayExpression([newInjectionObject]); - afLogger.warn(chalk.yellow(`⚠️ Replaced invalid injection at '${injectionPosition}' with array.`)); + console.log(chalk.yellow(`⚠️ Replaced invalid injection at '${injectionPosition}' with array.`)); } } else { crudValue.properties.push( b.objectProperty(b.identifier(injectionPosition), b.arrayExpression([newInjectionObject])) ); - afLogger.info(chalk.dim(`Added new array of injections at '${injectionPosition}' for '${crudType}'.`)); + console.log(chalk.dim(`Added new array of injections at '${injectionPosition}' for '${crudType}'.`)); } updateApplied = true; @@ -594,7 +593,7 @@ export async function updateCrudInjectionConfig(resourceId, crudType, injectionP const outputCode = recast.print(ast).code; await fs.writeFile(filePath, outputCode, 'utf-8'); - afLogger.info( + console.log( chalk.green( `✅ Successfully updated CRUD injection in resource file: ${filePath}` + (injectionLine !== null ? `:${injectionLine}` : '') @@ -602,7 +601,7 @@ export async function updateCrudInjectionConfig(resourceId, crudType, injectionP ); } catch (error) { - afLogger.error(chalk.red(`❌ Error processing resource file: ${filePath}`)); + console.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 befc6a0eb..d6c281d6a 100644 --- a/adminforth/commands/createCustomComponent/fileGenerator.js +++ b/adminforth/commands/createCustomComponent/fileGenerator.js @@ -4,7 +4,6 @@ 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 { @@ -32,7 +31,7 @@ async function generateVueContent(fieldType, { resource, column }) { ? path.join(__dirname, 'templates', 'customFields', `${fieldType}.vue.hbs`) : path.join(__dirname, 'templates', 'customCrud', `${fieldType}.vue.hbs`); - afLogger.info(chalk.dim(`Using template: ${templatePath}`)); + console.log(chalk.dim(`Using template: ${templatePath}`)); const context = { componentName, @@ -62,24 +61,24 @@ export async function generateComponentFile(componentFileName, fieldType, contex const customDirPath = path.resolve(projectRoot, customDirRelative); const absoluteComponentPath = path.resolve(customDirPath, componentFileName); if (fsSync.existsSync(absoluteComponentPath)) { - afLogger.warn(chalk.yellow(`⚠️ Component file already exists: ${absoluteComponentPath}`)); + console.log(chalk.yellow(`⚠️ Component file already exists: ${absoluteComponentPath}`)); return {"alreadyExists": true, "path": absoluteComponentPath} } try { await fs.mkdir(customDirPath, { recursive: true }); - afLogger.info(chalk.dim(`Ensured custom directory exists: ${customDirPath}`)); + console.log(chalk.dim(`Ensured custom directory exists: ${customDirPath}`)); const fileContent = await generateVueContent(fieldType, context); await fs.writeFile(absoluteComponentPath, fileContent, 'utf-8'); - afLogger.info(chalk.green(`✅ Generated component file: ${absoluteComponentPath}`)); + console.log(chalk.green(`✅ Generated component file: ${absoluteComponentPath}`)); return {"alreadyExists": false, "path": absoluteComponentPath} } catch (error) { - afLogger.error(chalk.red(`❌ Error creating component file at ${absoluteComponentPath}:`)); + console.error(chalk.red(`❌ Error creating component file at ${absoluteComponentPath}:`)); if (!error.message.includes('template')) { - afLogger.error(error); + console.error(error); } throw error; } @@ -92,22 +91,22 @@ export async function generateCrudInjectionComponent(componentFileName, crudType const absoluteComponentPath = path.resolve(customDirPath, componentFileName); if (fsSync.existsSync(absoluteComponentPath)) { - afLogger.warn(chalk.yellow(`⚠️ Component file already exists: ${absoluteComponentPath}`)); + console.log(chalk.yellow(`⚠️ Component file already exists: ${absoluteComponentPath}`)); return { alreadyExists: true, path: absoluteComponentPath }; } try { await fs.mkdir(customDirPath, { recursive: true }); - afLogger.warn(chalk.dim(`Ensured custom directory exists: ${customDirPath}`)); + console.log(chalk.dim(`Ensured custom directory exists: ${customDirPath}`)); const fileContent = await generateVueContent(crudType, context); await fs.writeFile(absoluteComponentPath, fileContent, 'utf-8'); - afLogger.info(chalk.green(`✅ Generated component file: ${absoluteComponentPath}`)); + console.log(chalk.green(`✅ Generated component file: ${absoluteComponentPath}`)); return { alreadyExists: false, path: absoluteComponentPath }; } catch (error) { - afLogger.error(chalk.red(`❌ Error creating component file at ${absoluteComponentPath}:`)); + console.error(chalk.red(`❌ Error creating component file at ${absoluteComponentPath}:`)); throw error; } } @@ -119,13 +118,13 @@ export async function generateLoginOrGlobalComponentFile(componentFileName, inje const absoluteComponentPath = path.resolve(customDirPath, componentFileName); if (fsSync.existsSync(absoluteComponentPath)) { - afLogger.warn(chalk.yellow(`⚠️ Component file already exists: ${absoluteComponentPath}`)); + console.log(chalk.yellow(`⚠️ Component file already exists: ${absoluteComponentPath}`)); return { alreadyExists: true, path: absoluteComponentPath }; } try { await fs.mkdir(customDirPath, { recursive: true }); - afLogger.info(chalk.dim(`Ensured custom directory exists: ${customDirPath}`)); + console.log(chalk.dim(`Ensured custom directory exists: ${customDirPath}`)); const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); @@ -139,11 +138,11 @@ export async function generateLoginOrGlobalComponentFile(componentFileName, inje const fileContent = await renderHBSTemplate(templatePath, context); await fs.writeFile(absoluteComponentPath, fileContent, 'utf-8'); - afLogger.info(chalk.green(`✅ Generated login injection component: ${absoluteComponentPath}`)); + console.log(chalk.green(`✅ Generated login injection component: ${absoluteComponentPath}`)); return { alreadyExists: false, path: absoluteComponentPath }; } catch (error) { - afLogger.error(chalk.red(`❌ Error creating login component at ${absoluteComponentPath}`)); + console.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 01fb1309e..243a8c666 100644 --- a/adminforth/commands/createCustomComponent/main.js +++ b/adminforth/commands/createCustomComponent/main.js @@ -4,7 +4,6 @@ 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 @@ -15,7 +14,7 @@ function sanitizeLabel(input){ } export default async function createComponent(args) { - afLogger.info('This command will help you to generate boilerplate for component.\n'); + console.log('This command will help you to generate boilerplate for component.\n'); const config = await loadAdminForthConfig(); const resources = config.resources; @@ -189,9 +188,6 @@ async function handleCrudPageInjectionCreation(config, resources) { const injectionPosition = await select({ message: 'Where exactly do you want to inject the component?', choices: [ - ...(crudType === 'create' || crudType === 'edit' - ? [{ name: '💾 Save button on create/edit page', value: 'saveButton' }, new Separator()] - : []), { name: '⬆️ Before Breadcrumbs', value: 'beforeBreadcrumbs' }, { name: '➡️ Before Action Buttons', value: 'beforeActionButtons' }, { name: '⬇️ After Breadcrumbs', value: 'afterBreadcrumbs' }, diff --git a/adminforth/commands/createCustomComponent/templates/customCrud/saveButton.vue.hbs b/adminforth/commands/createCustomComponent/templates/customCrud/saveButton.vue.hbs deleted file mode 100644 index 06ed5e2ac..000000000 --- a/adminforth/commands/createCustomComponent/templates/customCrud/saveButton.vue.hbs +++ /dev/null @@ -1,28 +0,0 @@ - - - - - diff --git a/adminforth/commands/postinstall.js b/adminforth/commands/postinstall.js index b838955d9..23e21cd35 100644 --- a/adminforth/commands/postinstall.js +++ b/adminforth/commands/postinstall.js @@ -2,16 +2,14 @@ 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)){ - afLogger.info('Installing SPA dependencies...'); + console.log('Installing SPA dependencies...'); execSync('npm ci', { cwd: spaPath, stdio: 'inherit' }); - afLogger.info('Installed spa dependencies'); + console.log('Installed spa dependencies'); } else { - afLogger.warn('SPA dependencies not found'); - afLogger.warn(`current directory: ${import.meta.dirname}`); + console.log('SPA dependencies not found'); + console.log('current directory', import.meta.dirname); } \ No newline at end of file diff --git a/adminforth/commands/proxy.ts b/adminforth/commands/proxy.ts index 61ddb6ebf..c498326c9 100644 --- a/adminforth/commands/proxy.ts +++ b/adminforth/commands/proxy.ts @@ -3,7 +3,6 @@ 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[] = []; @@ -24,8 +23,8 @@ import { afLogger } from '../modules/logger.js'; capturedLogs.push(args); } - afLogger.trace(`🪲 TMP proxy file: ${tmpFile}`); - afLogger.trace(`🪲 Current working directory: ${process.cwd()}`); + process.env.HEAVY_DEBUG && console.log(`🪲 TMP proxy file: ${tmpFile}`); + process.env.HEAVY_DEBUG && console.log(`🪲 Current working directory: ${process.cwd()}`); try { // Save code to a temp file diff --git a/adminforth/commands/utils.js b/adminforth/commands/utils.js index 4bb03b6bb..2f5492d8e 100644 --- a/adminforth/commands/utils.js +++ b/adminforth/commands/utils.js @@ -1,7 +1,6 @@ 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 @@ -132,7 +131,7 @@ export async function getInstance(file, currentDirectory) { let filePath = initialFilePath; if (file.endsWith(".ts")) { - afLogger.info(`Compiling TypeScript file: ${file}`); + console.log(`Compiling TypeScript file: ${file}`); try { execSync( `./node_modules/.bin/tsc ${filePath} --module ESNext --outDir ./dist`, @@ -141,7 +140,7 @@ export async function getInstance(file, currentDirectory) { } ); } catch (error) { - afLogger.error(`Error: Could not compile TypeScript file '${file}'`); + //console.log(`Error: Could not compile TypeScript file '${file}'`); } const distDir = path.join(currentDirectory, "dist"); processJsFilesInDir(distDir);