From 2d411790574bb83b4a278169b6f9facb40ac730f Mon Sep 17 00:00:00 2001 From: Thada Wangthammang Date: Sat, 20 Jan 2024 22:41:36 +0700 Subject: [PATCH] improve commandline interface --- .../azure-functions/src/handler-resolver.ts | 10 +-- packages/azure-functions/src/utils.ts | 10 +-- packages/core/package.json | 7 +- packages/core/src/init-nammatham.ts | 2 +- packages/core/src/logger.ts | 5 +- packages/core/src/nammatham-app.ts | 13 ++- packages/express/package.json | 5 +- packages/express/src/express-server.ts | 16 +++- .../src/trpc-azure-functions.ts | 6 +- pnpm-lock.yaml | 83 ++++++++++++++++--- tsconfig.json | 2 +- 11 files changed, 117 insertions(+), 42 deletions(-) diff --git a/packages/azure-functions/src/handler-resolver.ts b/packages/azure-functions/src/handler-resolver.ts index a501daa3..c7e88f1a 100644 --- a/packages/azure-functions/src/handler-resolver.ts +++ b/packages/azure-functions/src/handler-resolver.ts @@ -119,9 +119,7 @@ export class AzureFunctionsHandlerResolver extends BaseHandlerResolver { }); const startTime = performance.now(); warnUnsupportedFeature(endpoint); - logger.info( - `Executing 'Functions.${endpoint.name}' (Reason='This function was programmatically called via the host APIs.', Id=${context.invocationId})` - ); + logger.info(`Executing 'Functions.${endpoint.name}' (Id=${context.invocationId})`); let result: HttpResponse | string | undefined | unknown; try { result = await endpoint.invokeHandler(new HttpRequest(req), context); @@ -148,8 +146,8 @@ export class AzureFunctionsHandlerResolver extends BaseHandlerResolver { logger.warn(`\n\n${yellow('No functions registered, did you forget to add functions?')}\n`); } - logger.info(`Running with runtime: ${app.runtime}`); - console.log(`runtime: ${app.runtime}, isDevelopment: ${app.isDevelopment}`); + logger.debug(`Running with runtime: ${app.runtime}`); + logger.debug(`runtime: ${app.runtime}, isDevelopment: ${app.isDevelopment}`); if (app.runtime === 'express' && process.env.NAMMATHAM_ENV !== 'development') { throw new Error( @@ -158,7 +156,7 @@ export class AzureFunctionsHandlerResolver extends BaseHandlerResolver { ); } if (app.isDevelopment === true) { - logger.info(`Running in development mode`); + logger.debug(`Running in development mode`); logger.debug(`Skipping Register Azure Function handler in development mode`); return; } diff --git a/packages/azure-functions/src/utils.ts b/packages/azure-functions/src/utils.ts index 04a93253..e39d5f18 100644 --- a/packages/azure-functions/src/utils.ts +++ b/packages/azure-functions/src/utils.ts @@ -1,7 +1,7 @@ import type { AfterServerStartedMetadata, NammathamApp } from '@nammatham/core'; +import { gray, yellow } from 'colorette'; import { trimSlash } from '@nammatham/core'; -import { blue, green, yellow } from 'colorette'; import type { AzureFunctionsEndpoint } from './types'; @@ -29,11 +29,10 @@ export async function printRegisteredFunctions( .filter(func => func.type === 'azure-functions') .filter(func => func.endpointOption?.type === 'http') as AzureFunctionsEndpoint[]; if (azureFunctions.length === 0) return []; - await delay(100); console.log(`\n${yellow('Functions:')}\n`); for (const func of azureFunctions) { const methods = `[${getMethods(func).join(',')}]`; - console.log(`\t${yellow(func.name)}: ${blue(methods)} ${green(getFullUrl(func, option.port))}\n`); + console.log(` - ${func.name} ${gray(methods)} ${gray(getFullUrl(func, option.port))}`); } console.log(''); return azureFunctions; @@ -50,12 +49,11 @@ export async function printRegisteredNonHttpFunctions( .filter(func => func.type === 'azure-functions') .filter(func => func.endpointOption?.type !== 'http') as AzureFunctionsEndpoint[]; if (azureFunctions.length === 0) return []; - await delay(100); console.log(`${yellow(`----------------------------------------------`)}\n`); console.log(`\n${yellow('Non-HTTP Functions (In Develpment Mode Only):')}\n`); for (const func of azureFunctions) { - const methods = `[GET]`; - console.log(`\t${yellow(func.name)}: ${blue(methods)} ${green(getFullUrl(func, option.port))}\n`); + const methods = `[${getMethods(func).join(',')}]`; + console.log(` - ${func.name} ${gray(methods)} ${gray(getFullUrl(func, option.port))}`); } console.log(''); return azureFunctions; diff --git a/packages/core/package.json b/packages/core/package.json index 9f2be98c..5fbc6350 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -20,11 +20,11 @@ "author": "Thada Wangthammang", "license": "MIT", "dependencies": { + "@types/express": "^4.17.21", "colorette": "^2.0.20", "pino": "^8.17.1", "pino-pretty": "^10.3.0", - "undici": "5.20.0", - "@types/express": "^4.17.21" + "undici": "5.20.0" }, "repository": { "type": "git", @@ -32,5 +32,8 @@ }, "publishConfig": { "registry": "https://registry.npmjs.org/" + }, + "devDependencies": { + "pino-dev": "^4.0.3" } } \ No newline at end of file diff --git a/packages/core/src/init-nammatham.ts b/packages/core/src/init-nammatham.ts index 2ddce3c1..c94280c4 100644 --- a/packages/core/src/init-nammatham.ts +++ b/packages/core/src/init-nammatham.ts @@ -21,7 +21,7 @@ function createRuntime>(adapter?: Ad export const initNammatham = { create = DefaultAdapter>(adapter?: Adapter): NammathamRuntime { - logger.info(`Using adapter: ${yellow(adapter?.constructor.name ?? 'DefaultAdapter')}`); + logger.debug(`Using adapter: ${yellow(adapter?.constructor.name ?? 'DefaultAdapter')}`); if (adapter === undefined) { return createRuntime(new DefaultAdapter() as any); } diff --git a/packages/core/src/logger.ts b/packages/core/src/logger.ts index 028983e2..f1ece34a 100644 --- a/packages/core/src/logger.ts +++ b/packages/core/src/logger.ts @@ -4,10 +4,7 @@ const isDevelopment = process.env.NAMMATHAM_ENV === 'development'; export const _logger = pino({ level: process.env.NAMMATHAM_LOG_LEVEL || 'info', transport: { - target: 'pino-pretty', - options: { - colorize: true, - }, + target: 'pino-dev', }, }); diff --git a/packages/core/src/nammatham-app.ts b/packages/core/src/nammatham-app.ts index 7e2b1a8a..ffb4ff7b 100644 --- a/packages/core/src/nammatham-app.ts +++ b/packages/core/src/nammatham-app.ts @@ -1,10 +1,14 @@ -import { magenta } from 'colorette'; +import { bgBlue, blue } from 'colorette'; import type { NammamthamEndpoint } from './types'; import type { BaseHandlerResolver } from './bases'; import { logger } from './main'; +export async function logo() { + return `${bgBlue(`\n nammatham `)} ${blue('v' + (await import('../package.json')).version)}`; +} + export class NammathamApp { protected readonly _functions: NammamthamEndpoint[] = []; /** @@ -20,6 +24,7 @@ export class NammathamApp { * because Azure Functions will start the server for us. */ private _isDevelopment: boolean | undefined; + public readonly startTime = performance.now(); constructor(public readonly handlerResolver: BaseHandlerResolver) {} @@ -30,8 +35,8 @@ export class NammathamApp { async start() { logger.debug('Registering functions...'); await this.handlerResolver.resolveRegisterHandler(this); - logger.info('All functions registered'); - console.log(magenta(`\nStart Nammatham, Type-safe Serverless Library\n`)); + logger.debug('All functions registered'); + console.log(`${logo()} \n`); } addFunctions(...functions: NammamthamEndpoint[]) { @@ -44,7 +49,7 @@ export class NammathamApp { addFunction(func: NammamthamEndpoint) { logger.debug(`Adding function "${func.name}" on route: ${func.endpointOption?.route}`); this._functions.push(func); - logger.info(`Function "${func.name}" added`); + logger.debug(`Function "${func.name}" added`); return this; } diff --git a/packages/express/package.json b/packages/express/package.json index 4c1ffb4f..b455cf1f 100644 --- a/packages/express/package.json +++ b/packages/express/package.json @@ -21,8 +21,9 @@ "license": "MIT", "dependencies": { "@nammatham/core": "2.0.0-alpha.8", - "express": "^4.18.2", - "@types/express": "^4.17.21" + "@types/express": "^4.17.21", + "colorette": "^2.0.20", + "express": "^4.18.2" }, "repository": { "type": "git", diff --git a/packages/express/src/express-server.ts b/packages/express/src/express-server.ts index 9aea1ea2..2b1efb71 100644 --- a/packages/express/src/express-server.ts +++ b/packages/express/src/express-server.ts @@ -1,7 +1,8 @@ import type { BaseHandlerResolver, NammathamApp } from '@nammatham/core'; import express from 'express'; -import { logger } from '@nammatham/core'; +import { logger, logo } from '@nammatham/core'; +import { blue, gray, greenBright } from 'colorette'; import type { NammathamHttpHandlerOption } from './types'; @@ -27,7 +28,7 @@ export function expressPlugin(option?: ExpressServerOption) { } app.setRuntime('express'); app.setDevelopment(isDevelopment); - logger.info(`Using plugin: expressPlugin`); + logger.debug(`Using plugin: expressPlugin`); startExpress( { handlerResolver, @@ -63,7 +64,16 @@ export function startExpress( ); expressApp.listen(port, async () => { - logger.info(`Dev Server started at http://localhost:${port}`); + console.clear(); + const endTime = performance.now(); + const durationMs = Math.floor(endTime - app.startTime); + logger.debug(`Server started at http://localhost:${port}`); + console.log(`${await logo()} ${gray(`ready in ${durationMs}ms`)}\n`); + console.log(`\n${blue('Express server started')}\n`); + console.log(` ┃ Local ${greenBright(`http://localhost:${port}`)}`); + console.log(` ┃ Host ${gray('Not Available')} \n`); + await handlerResolver.afterServerStarted(app, { port, allowAllFunctionsAccessByHttp }); + // console.log(`\nServer Ready \n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n`); }); } diff --git a/packages/trpc-azure-functions/src/trpc-azure-functions.ts b/packages/trpc-azure-functions/src/trpc-azure-functions.ts index fd0737cd..5d455cc4 100644 --- a/packages/trpc-azure-functions/src/trpc-azure-functions.ts +++ b/packages/trpc-azure-functions/src/trpc-azure-functions.ts @@ -24,9 +24,11 @@ export interface TrpcAzureFunctionsPluginOption { * Unstable, some features are not implemented yet. */ -export function unstable__tRpcAzureFunctionsPlugin(option: TrpcAzureFunctionsPluginOption) { +export function unstable__tRpcAzureFunctionsPlugin( + option: TrpcAzureFunctionsPluginOption +) { return (app: NammathamApp, handlerResolver: BaseHandlerResolver) => { - logger.info(`Using plugin: tRPC for AzureFunctions`); + logger.debug(`Using plugin: tRPC for AzureFunctions`); const prefix = trimSlash(option?.prefix ?? '/trpc'); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 572fdb98..25bd24ef 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -238,6 +238,10 @@ importers: undici: specifier: 5.20.0 version: 5.20.0 + devDependencies: + pino-dev: + specifier: ^4.0.3 + version: 4.0.3 packages/express: dependencies: @@ -247,6 +251,9 @@ importers: '@types/express': specifier: ^4.17.21 version: 4.17.21 + colorette: + specifier: ^2.0.20 + version: 2.0.20 express: specifier: ^4.18.2 version: 4.18.2 @@ -576,6 +583,10 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true + /@hapi/bourne@3.0.0: + resolution: {integrity: sha512-Waj1cwPXJDucOib4a3bAISsKJVb15MKi9IvmTI/7ssVEm6sywXGjVJDhl6/umt1pK1ZS7PacXU3A1PmFKHEZ2w==} + dev: true + /@humanwhocodes/config-array@0.11.14: resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} engines: {node: '>=10.10.0'} @@ -1423,7 +1434,6 @@ packages: engines: {node: '>=6.5'} dependencies: event-target-shim: 5.0.1 - dev: false /accepts@1.3.8: resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} @@ -1528,6 +1538,16 @@ packages: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} dev: true + /args@5.0.3: + resolution: {integrity: sha512-h6k/zfFgusnv3i5TU08KQkVKuCPBtL/PWQbWkHUxvJrZ2nAyeaUupneemcrgn1xmqxPQsPIzwkUhOpoqPDRZuA==} + engines: {node: '>= 6.0.0'} + dependencies: + camelcase: 5.0.0 + chalk: 2.4.2 + leven: 2.1.0 + mri: 1.1.4 + dev: true + /array-buffer-byte-length@1.0.0: resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==} dependencies: @@ -1568,7 +1588,6 @@ packages: /atomic-sleep@1.0.0: resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} engines: {node: '>=8.0.0'} - dev: false /available-typed-arrays@1.0.5: resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} @@ -1657,7 +1676,6 @@ packages: dependencies: base64-js: 1.5.1 ieee754: 1.2.1 - dev: false /bundle-require@4.0.2(esbuild@0.19.11): resolution: {integrity: sha512-jwzPOChofl67PSTW2SGubV9HBQAhhR2i6nskiOThauo9dzwDUgOWQScFVaJkjEfYX+UXiD+LEx8EblQMc2wIag==} @@ -1698,6 +1716,11 @@ packages: engines: {node: '>=6'} dev: true + /camelcase@5.0.0: + resolution: {integrity: sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==} + engines: {node: '>=6'} + dev: true + /chai@4.4.1: resolution: {integrity: sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==} engines: {node: '>=4'} @@ -1885,6 +1908,10 @@ packages: which: 2.0.2 dev: true + /date-fns@3.0.5: + resolution: {integrity: sha512-Q4Tq5c5s/Zl/zbgdWf6pejn9ru7UwdIlLfvEEg1hVsQNQ7LKt76qIduagIT9OPK7+JCv1mAKherdU6bOqGYDnw==} + dev: true + /dateformat@4.6.3: resolution: {integrity: sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==} dev: false @@ -2330,12 +2357,10 @@ packages: /event-target-shim@5.0.1: resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} engines: {node: '>=6'} - dev: false /events@3.3.0: resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} engines: {node: '>=0.8.x'} - dev: false /execa@5.1.1: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} @@ -3133,6 +3158,11 @@ packages: json-buffer: 3.0.1 dev: true + /leven@2.1.0: + resolution: {integrity: sha512-nvVPLpIHUxCUoRLrFqTgSxXJ614d8AgQoWl7zPe/2VadE8+1dpU3LBhowRuBAcuwruWtOdD8oYC9jDNJjXDPyA==} + engines: {node: '>=0.10.0'} + dev: true + /levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} @@ -3336,6 +3366,11 @@ packages: ufo: 1.3.2 dev: true + /mri@1.1.4: + resolution: {integrity: sha512-6y7IjGPm8AzlvoUrwAaw1tLnUBudaS3752vcd8JtrpGGQn+rXIe63LFVHm/YMwtqAuh+LJPCFdlLYPWM1nYn6w==} + engines: {node: '>=4'} + dev: true + /ms@2.0.0: resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} dev: false @@ -3745,7 +3780,27 @@ packages: dependencies: readable-stream: 4.5.2 split2: 4.2.0 - dev: false + + /pino-dev@4.0.3: + resolution: {integrity: sha512-MrJj1uUZwAcucyZ2t1TspBcYacUBxw6WNXOzvJ/iy8V+LbyoEsJ3vxooU1wS/Z1kjOPAs2yODTfqrBBCadpYDA==} + engines: {node: '>=8.10.0'} + hasBin: true + dependencies: + '@hapi/bourne': 3.0.0 + args: 5.0.3 + chalk: 4.1.2 + date-fns: 3.0.5 + debug: 4.3.4 + joycon: 3.1.1 + pino-abstract-transport: 1.1.0 + pump: 3.0.0 + readable-stream: 4.5.1 + sonic-boom: 3.8.0 + split2: 4.2.0 + strip-ansi: 6.0.1 + transitivePeerDependencies: + - supports-color + dev: true /pino-pretty@10.3.1: resolution: {integrity: sha512-az8JbIYeN/1iLj2t0jR9DV48/LQ3RC6hZPpapKPkb84Q+yTidMCpgWxIT3N0flnBDilyBQ1luWNpOeJptjdp/g==} @@ -3853,7 +3908,6 @@ packages: /process@0.11.10: resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} engines: {node: '>= 0.6.0'} - dev: false /proxy-addr@2.0.7: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} @@ -3876,7 +3930,6 @@ packages: dependencies: end-of-stream: 1.4.4 once: 1.4.0 - dev: false /punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} @@ -3934,6 +3987,17 @@ packages: util-deprecate: 1.0.2 dev: true + /readable-stream@4.5.1: + resolution: {integrity: sha512-uQjbf34vmf/asGnOHQEw07Q4llgMACQZTWWa4MmICS0IKJoHbLwKCy71H3eR99Dw5iYejc6W+pqZZEeqRtUFAw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + abort-controller: 3.0.0 + buffer: 6.0.3 + events: 3.3.0 + process: 0.11.10 + string_decoder: 1.3.0 + dev: true + /readable-stream@4.5.2: resolution: {integrity: sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -3943,7 +4007,6 @@ packages: events: 3.3.0 process: 0.11.10 string_decoder: 1.3.0 - dev: false /readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} @@ -4220,7 +4283,6 @@ packages: resolution: {integrity: sha512-ybz6OYOUjoQQCQ/i4LU8kaToD8ACtYP+Cj5qd2AO36bwbdewxWJ3ArmJ2cr6AvxlL2o0PqnCcPGUgkILbfkaCA==} dependencies: atomic-sleep: 1.0.0 - dev: false /source-map-js@1.0.2: resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} @@ -4264,7 +4326,6 @@ packages: /split2@4.2.0: resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} engines: {node: '>= 10.x'} - dev: false /sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} diff --git a/tsconfig.json b/tsconfig.json index 4c82a904..ed778c84 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -37,7 +37,7 @@ // "jest" ], /* Specify type package names to be included without being referenced in a source file. */ // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ - // "resolveJsonModule": true, /* Enable importing .json files */ + "resolveJsonModule": true, /* Enable importing .json files */ // "noResolve": true, /* Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project. */ /* JavaScript Support */