Skip to content

Commit

Permalink
feat: support request notice log & string log format
Browse files Browse the repository at this point in the history
  • Loading branch information
cxtom committed Mar 10, 2021
1 parent 24df2e3 commit c9eaa65
Show file tree
Hide file tree
Showing 23 changed files with 559 additions and 59 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,6 @@ dist
.tern-port

# mac
.DS_Store
.DS_Store

log/
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
# hoth
A Node.js framework based on fastify

under development
3 changes: 3 additions & 0 deletions example/hoth-quickstart/src/config/plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default {
'@hoth/app-autoload': {},
};
16 changes: 16 additions & 0 deletions example/hoth-quickstart/src/controller/app/app.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import {Controller, getFastifyInstanceByAppName, GET} from '@hoth/decorators';
import {FastifyReply, FastifyRequest} from 'fastify';

@Controller('/app')
export default class AppController {

private readonly service = getFastifyInstanceByAppName('quickstart');

@GET()
getApp(req: FastifyRequest, reply: FastifyReply) {
reply.log.info(`config test value ${req.$appConfig.get('test')}`);
reply.log.error({err: new Error('hello1')});
reply.log.warn('test error');
reply.send('ok');
}
}
15 changes: 0 additions & 15 deletions example/hoth-quickstart/src/controller/post/post.controller.ts

This file was deleted.

9 changes: 5 additions & 4 deletions nodemon.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{
"watch": ["packages/*/src", "example/*/src"],
"ignore": ["*.test.ts"],
"watch": ["*.ts"],
"ignore": ["*.test.ts", "node_modules/*", "*.d.ts"],
"ext": "ts,js",
"exec": "yarn run build && yarn run hoth start --app-dir='example/hoth-quickstart/dist'",
"legacyWatch": true
"exec": "yarn run build && NODE_ENV=development yarn run hoth start --app-dir='example/hoth-quickstart/dist' --app-name='quickstart'",
"legacyWatch": true,
"require": ["source-map-support/register"]
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
"husky": "^4.3.8",
"lerna": "^3.22.1",
"nodemon": "^2.0.7",
"source-map-support": "^0.5.19",
"ts-node": "^9.1.1",
"typescript": "^4.1.3"
}
Expand Down
1 change: 1 addition & 0 deletions packages/app-autoload/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"config": "^3.3.3",
"fastify-autoload": "^3.4.2",
"fastify-plugin": "^3.0.0",
"resolve-from": "^5.0.0",
"tslib": "^2.1.0"
},
"files": [
Expand Down
16 changes: 16 additions & 0 deletions packages/app-autoload/src/hook/onResponse.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import {FastifyReply, FastifyRequest} from 'fastify';

declare module 'fastify' {
interface FastifyLoggerInstance {
notice: (...args: any[]) => void;
}
}

export default function (req: FastifyRequest, reply: FastifyReply, done) {
const responseTime = reply.getResponseTime();
reply.log.notice({
res: reply,
responseTime: responseTime.toFixed(1),
}, 'request completed');
done();
}
8 changes: 8 additions & 0 deletions packages/app-autoload/src/hook/preHandlerFactory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import {FastifyReply, FastifyRequest} from 'fastify';

export default function (app: string) {
return function (req: FastifyRequest, reply: FastifyReply, done) {
req.log = reply.log = reply.log.child({req, app});
done();
};
}
88 changes: 64 additions & 24 deletions packages/app-autoload/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@ import autoload from 'fastify-autoload';
import {existsSync, readdirSync} from 'fs';
import {FastifyInstance, FastifyPluginAsync} from 'fastify';
import fp from 'fastify-plugin';
import resolveFrom from 'resolve-from';
import {bootstrap} from '@hoth/decorators';
import {exit, loadModule} from '@hoth/utils';
import onResponse from './hook/onResponse';
import preHandlerFactory from './hook/preHandlerFactory';

interface AppAutoload {
dir: string;
Expand All @@ -26,8 +29,13 @@ interface AppConfig {
prefix: string;
name: string;
rootPath: string;
pluginConfig: {
[name: string]: any;
};
}
interface AppsLoaded {
apps: AppConfig[];
}

interface PluginAppConfig extends AppConfig {
[key: string]: any;
controllerPath: string;
Expand All @@ -36,15 +44,6 @@ interface PluginAppConfig extends AppConfig {
entryPath: string;
}

declare module 'fastify' {
interface FastifyInstance {
readonly appConfig: {
get: (property: string) => any;
has: (property: string) => boolean;
};
}
}

async function load(appConfig: AppConfig, childInstance: FastifyInstance) {

const pluginAppConfig: PluginAppConfig = {
Expand All @@ -67,7 +66,7 @@ async function load(appConfig: AppConfig, childInstance: FastifyInstance) {
...appConfig,
});

childInstance.decorate('appConfig', {
childInstance.decorateRequest('$appConfig', {
get(property: string | string[]) {
const props = Array.isArray(property)
? [appConfig.name, ...property]
Expand All @@ -78,22 +77,25 @@ async function load(appConfig: AppConfig, childInstance: FastifyInstance) {
},
});

// load controllers
if (!existsSync(pluginAppConfig.controllerPath)) {
exit(`Did not find \`controller\` dir in ${appConfig.dir}`);
return;
// load module plugins
if (appConfig.pluginConfig) {
for await (const [name, config] of Object.entries(appConfig.pluginConfig)) {
if (name === '@hoth/app-autoload') {
continue;
}
let mod: any = resolveFrom.silent(appConfig.dir, name);
mod = mod.__esModule ? mod.default : mod;
if (mod) {
await childInstance.register(mod, config);
}
}
}
await childInstance.register(bootstrap, {
directory: pluginAppConfig.controllerPath,
mask: /\.controller\.js$/,
appName: appConfig.name,
});

// register app plugins
const appEntryModule: FastifyPluginAsync = await loadModule(pluginAppConfig.entryPath);
await childInstance.register(appEntryModule, {...appConfig});
if (existsSync(pluginAppConfig.pluginPath)) {
childInstance.register(autoload, {
await childInstance.register(autoload, {
dir: pluginAppConfig.pluginPath,
dirNameRoutePrefix: false,
ignorePattern: /.*(test|spec).js/,
Expand All @@ -104,11 +106,34 @@ async function load(appConfig: AppConfig, childInstance: FastifyInstance) {
});
}

// load controllers
if (!existsSync(pluginAppConfig.controllerPath)) {
exit(`Did not find \`controller\` dir in ${appConfig.dir}`);
return;
}
await childInstance.register(bootstrap, {
directory: pluginAppConfig.controllerPath,
mask: /\.controller\.js$/,
appName: appConfig.name,
});

childInstance.addHook('preHandler', preHandlerFactory(appConfig.name));
childInstance.addHook('onResponse', onResponse);

return childInstance;
}

export default fp(async function (instance: FastifyInstance, opts: AppAutoload) {
async function loadPluginConfig(appRoot: string) {
try {
const result = await loadModule(join(appRoot, 'config/plugin'));
return result;
}
catch (e) {
return null;
}
}

export async function getApps(opts: AppAutoload) {
const {
dir,
rootPath,
Expand All @@ -129,23 +154,27 @@ export default fp(async function (instance: FastifyInstance, opts: AppAutoload)
let apps: AppConfig[] = [];

if (existsSync(join(appRoot, 'app.js'))) {
const pluginConfig = await loadPluginConfig(appRoot);
apps = [{
dir: appRoot,
prefix,
name: name || (prefix === '/' ? 'root' : prefix.slice(1)),
rootPath,
pluginConfig,
}];
}
else {
const dirs = readdirSync(appRoot, {withFileTypes: true});
for (const dir of dirs) {
const dirPath = resolve(appRoot, dir.name);
if (dir.isDirectory() && existsSync(join(dirPath, 'app.js'))) {
const pluginConfig = await loadPluginConfig(dirPath);
apps.push({
dir: dirPath,
prefix: `${prefix}${prefix === '/' ? '' : '/'}${dir}`,
name: dir.name,
rootPath,
pluginConfig,
});
}
}
Expand All @@ -156,14 +185,25 @@ export default fp(async function (instance: FastifyInstance, opts: AppAutoload)
return;
}

return apps;
}

export default fp(async function (instance: FastifyInstance, opts: AppAutoload | AppsLoaded) {

let apps: AppConfig[];
if ((opts as AppsLoaded).apps) {
apps = (opts as AppsLoaded).apps;
}
else {
apps = await getApps(opts as AppAutoload);
}

for await (const appConfig of apps) {
await instance.register(load.bind(null, appConfig), {
prefix: appConfig.prefix,
});
}

console.log(apps);

return;

}, {
Expand Down
1 change: 0 additions & 1 deletion packages/cli/src/parseArgs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ export default function (args): Args {
debugPort: 9320,
appDir: 'app',
appPrefix: '/',
appName: 'hoth',
},
});

Expand Down
21 changes: 15 additions & 6 deletions packages/cli/src/start.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import Fastify from 'fastify';
import isDocker from 'is-docker';
import parseArgs from './parseArgs';
import {exit, requireFastifyForModule} from '@hoth/utils';
import appAutoload from '@hoth/app-autoload';
import appAutoload, {getApps} from '@hoth/app-autoload';
import createLogger from '@hoth/logger';
import {showHelpForCommand} from './util';

const listenAddressDocker = '0.0.0.0';
Expand Down Expand Up @@ -41,17 +42,25 @@ async function runFastify(opts) {
}
}

const rootPath = process.env.ROOT_PATH || process.cwd();
const apps = await getApps({
dir: opts.appDir,
prefix: opts.appPrefix,
name: opts.appName,
rootPath,
});

const fastifyInstance = fastify({
logger: false,
logger: createLogger({
apps,
rootPath,
}),
disableRequestLogging: true,
pluginTimeout: 60 * 1000,
});

await fastifyInstance.register(appAutoload, {
dir: opts.appDir,
prefix: opts.appPrefix,
name: opts.appName,
rootPath: process.env.ROOT_PATH || process.cwd(),
apps,
});

let address;
Expand Down
3 changes: 2 additions & 1 deletion packages/cli/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
},
"references": [
{ "path": "../utils" },
{ "path": "../app-autoload" }
{ "path": "../app-autoload" },
{ "path": "../logger" }
],
}
12 changes: 12 additions & 0 deletions packages/decorators/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,15 @@ export async function bootstrap(fastify: FastifyInstance, config: BootstrapConfi
appFastifyInstanceTokenMap.set(appName, fastify);
return await bootstrapInner(fastify, config);
}

declare module 'fastify' {
interface FastifyRequest {
readonly $appConfig: {
get: (property: string) => any;
};
module?: string;
logid?: string;
product?: string;
}
}

7 changes: 6 additions & 1 deletion packages/logger/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,13 @@
},
"homepage": "https://github.com/cxtom/hoth#readme",
"dependencies": {
"flatstr": "^1.0.12",
"fs-extra": "^9.1.0",
"pino": "^6.11.1",
"resolve-from": "^5.0.0",
"tslib": "^2.1.0"
"secure-json-parse": "^2.3.1",
"tslib": "^2.1.0",
"uuid-random": "^1.3.2"
},
"files": [
"dist"
Expand Down
Loading

0 comments on commit c9eaa65

Please sign in to comment.