Skip to content

Commit

Permalink
feat: support molecule app
Browse files Browse the repository at this point in the history
  • Loading branch information
yuanxueran committed Apr 20, 2021
1 parent 2367f2b commit 876dc3b
Show file tree
Hide file tree
Showing 42 changed files with 797 additions and 28 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ Create a app:
hoth generate --app-name="myapp" myapp
```

Create a molecule app:
```sh
hoth generate --app-name="myapp" --app-type="molecule" myapp
```

> option `--app-name` is required
Install dependencies:
Expand Down
17 changes: 17 additions & 0 deletions example/hoth-molecule/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# hoth-molecule

### Install and Run

Using NPM:

```sh
$ npm install
$ npm run dev
```

Using Yarn:

```sh
$ yarn
$ yarn dev
```
7 changes: 7 additions & 0 deletions example/hoth-molecule/nodemon.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"watch": ["*.ts", "*.json"],
"ignore": ["*.test.ts", "*.spec.ts", "node_modules/*", "*.d.ts"],
"ext": "ts,js,tpl",
"exec": "NODE_ENV=development npm run build && NODE_ENV=development hoth start --app-dir='dist' --app-name='hoth-molecule' --app-prefix='/hoth-molecule'",
"legacyWatch": true
}
58 changes: 58 additions & 0 deletions example/hoth-molecule/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
{
"name": "@baidu/molecule-myapp",
"version": "1.0.0",
"description": "molecule app",
"main": "dist/app.js",
"private": true,
"scripts": {
"lint-staged": "lint-staged",
"lint": "eslint src",
"dev": "nodemon",
"build-serve": "tsc --build ./serve/tsconfig.json && gulp -f ./serve/gulpfile.esm.js",
"build-client": "tsc --build ./src/tsconfig.node.json",
"build": "npm run build-serve && npm run build-client"
},
"repository": {
"type": "git",
"url": "ssh://git@icode.baidu.com:8235/baidu/myapp-fe/node-ui"
},
"author": "",
"license": "ISC",
"lint-staged": {
"**/*.ts": [
"eslint"
]
},
"husky": {
"hooks": {
"pre-commit": "lint-staged",
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
}
},
"devDependencies": {
"@babel/eslint-plugin": "^7.12.13",
"@commitlint/cli": "^11.0.0",
"@commitlint/config-conventional": "^11.0.0",
"@ecomfe/eslint-config": "^7.0.0",
"@hoth/cli": "^1.0.2",
"@tsconfig/node12": "^1.0.7",
"@types/node": "^14.14.22",
"@typescript-eslint/eslint-plugin": "^4.14.2",
"@typescript-eslint/parser": "^4.14.2",
"eslint": "^7.19.0",
"esm": "^3.2.25",
"fastify": "^3.11.0",
"gulp": "^4.0.2",
"husky": "^4.3.8",
"lerna": "^3.22.1",
"lint-staged": "^10.5.4",
"nodemon": "^2.0.7",
"source-map-support": "^0.5.19",
"ts-node": "^9.1.1",
"typescript": "^4.1.3"
},
"dependencies": {
"nunjucks": "^3.2.3",
"point-of-view": "^4.14.0"
}
}
1 change: 1 addition & 0 deletions example/hoth-molecule/serve/READE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# nodeui 服务器端逻辑
4 changes: 4 additions & 0 deletions example/hoth-molecule/serve/app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import {FastifyInstance} from 'fastify';
export default async function main(fastify: FastifyInstance) {
return fastify;
}
14 changes: 14 additions & 0 deletions example/hoth-molecule/serve/config/molecule.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"controllers": [
{
"name": "index",
"ctrlPath": "view/main/index",
"httptype": "get"
},
{
"name": "test",
"ctrlPath": "view/main/index",
"httptype": "post"
}
]
}
7 changes: 7 additions & 0 deletions example/hoth-molecule/serve/gulpfile.esm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import {src, dest, series} from 'gulp';

function copyAssets() {
return src('./config/*').pipe(dest('../dist/config'));
}

export default series(copyAssets);
12 changes: 12 additions & 0 deletions example/hoth-molecule/serve/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"compilerOptions": {
"target": "es2019",
"module": "commonjs",
"moduleResolution": "Node",
"esModuleInterop": true,
"rootDir": "./",
"outDir": "../dist",
"declaration": false,
"composite": false
}
}
5 changes: 5 additions & 0 deletions example/hoth-molecule/src/main/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export class Controller {
render(data: any) {
return `${data.content}`;
}
}
10 changes: 10 additions & 0 deletions example/hoth-molecule/src/tsconfig.node.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"target": "es2019",
"module": "commonjs",
"moduleResolution": "Node",
"rootDir": "./",
"outDir": "../dist/view"
}
}
12 changes: 12 additions & 0 deletions example/hoth-molecule/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"compilerOptions": {
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"importHelpers": true,
"esModuleInterop": true,
"sourceMap": false,
"declaration": false,
"rootDir": "./",
"composite": false
}
}
1 change: 1 addition & 0 deletions packages/app-autoload/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"@hoth/decorators": "^1.0.7",
"@hoth/logger": "^1.0.7",
"@hoth/utils": "^1.0.8",
"@hoth/molecule": "^1.0.0",
"config": "^3.3.3",
"fastify-autoload": "^3.4.2",
"fastify-plugin": "^3.0.0",
Expand Down
83 changes: 72 additions & 11 deletions packages/app-autoload/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Config from 'config';
import {resolve, join, isAbsolute} from 'path';
import autoload from 'fastify-autoload';
import {existsSync, readdirSync} from 'fs';
import {FastifyInstance, FastifyPluginAsync} from 'fastify';
import {FastifyInstance, FastifyPluginAsync, FastifyRequest} from 'fastify';
import fp from 'fastify-plugin';
import resolveFrom from 'resolve-from';
import {bootstrap} from '@hoth/decorators';
Expand All @@ -19,6 +19,7 @@ import onResponse from './hook/onResponse';
import preHandlerFactory from './hook/preHandlerFactory';
import onRequestFactory from './hook/onRequestFactory';
import {preHandler as loggerMiddleware} from '@hoth/logger';
import {molecule} from '@hoth/molecule';

interface AppAutoload {
dir: string;
Expand Down Expand Up @@ -46,9 +47,68 @@ interface PluginAppConfig extends AppConfig {
pluginPath: string;
entryPath: string;
}
interface MoleculeController {
ctrlPath: string;
name: string;
httpType: string;
json?: boolean;
}

async function load(appConfig: AppConfig, childInstance: FastifyInstance) {
interface MoleculeConfig {
controllers: MoleculeController[];
}

/**
* 加载 molecule app
*/
async function loadMoleculeApp(appConfig: AppConfig, instance: FastifyInstance) {
const moleculeConfPath = join(appConfig.dir, 'config/molecule.json');
if (!existsSync(moleculeConfPath)) {
return;
}
const {controllers} = await loadModule(moleculeConfPath) as MoleculeConfig;

controllers.forEach(item => {
let httpType = item.httpType;
let ctrlName = item.name;

// eslint-disable-next-line @typescript-eslint/no-unused-vars
instance[httpType](`/${ctrlName}`, async (request: FastifyRequest, reply) => {
let data = {} as any;

if (httpType === 'post') {
data = request.body || request.query || {};
}
else if (httpType === 'get') {
data = request.query;
}
// 本地 mock 数据
if (process.env.DATA_MOCK) {
data = await loadModule(join(appConfig.dir, `mock/${ctrlName}.json`));
}

// @ts-ignore
let ret = await instance.molecule(item.ctrlPath, data, {
root: appConfig.dir,
appName: appConfig.name,
name: ctrlName,
logger: instance.log,
});
if (item.json) {
return ret ? {
statusCode: 200,
data: ret,
} : {
statusCode: 500,
message: 'render error',
};
}
return ret;
});
});
}

async function load(appConfig: AppConfig, childInstance: FastifyInstance) {
const pluginAppConfig: PluginAppConfig = {
...appConfig,
controllerPath: join(appConfig.dir, 'controller'),
Expand Down Expand Up @@ -100,10 +160,12 @@ async function load(appConfig: AppConfig, childInstance: FastifyInstance) {
};

childInstance.decorate('$appConfig', configProxy);
childInstance.decorate('molecule', molecule);

// register app plugins
const appEntryModule: FastifyPluginAsync = await loadModule(pluginAppConfig.entryPath);
await appEntryModule(childInstance, {...appConfig});

if (existsSync(pluginAppConfig.pluginPath)) {
await childInstance.register(autoload, {
dir: pluginAppConfig.pluginPath,
Expand All @@ -117,18 +179,17 @@ async function load(appConfig: AppConfig, childInstance: FastifyInstance) {
}

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

childInstance.addHook('onRequest', onRequestFactory(configProxy, childInstance));

childInstance.addHook('preHandler', preHandlerFactory(appConfig.name));
childInstance.addHook('preHandler', loggerMiddleware);
childInstance.addHook('onResponse', onResponse);
Expand Down
3 changes: 2 additions & 1 deletion packages/app-autoload/src/module.d.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
declare module 'config';
declare module 'config';
declare module '@hoth/molecule';
5 changes: 3 additions & 2 deletions packages/app-autoload/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
},
"references": [
{ "path": "../utils" },
{ "path": "../decorators" }
],
{ "path": "../decorators" },
{ "path": "../molecule" }
]
}
26 changes: 14 additions & 12 deletions packages/cli/src/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,19 @@ import generify from 'generify';
import parseArgs from './parseArgs';
import chalk from 'chalk';

const template = {
dir: 'app',
logInstructions: function () {
console.log('debug', 'saved package.json');
console.log('info', 'project generated successfully');
console.log('debug', `run '${chalk.bold('npm install')}' to install the dependencies`);
console.log('debug', `run '${chalk.bold('npm build')}' to compile the application`);
console.log('debug', `run '${chalk.bold('npm run dev')}' to start the application`);
console.log('debug', `run '${chalk.bold('npm test')}' to execute the unit tests`);
},
};
function getTemplate(type?: string) {
return {
dir: (type === 'molecule') ? 'molecule-app' : 'app',
logInstructions: function () {
console.log('debug', 'saved package.json');
console.log('info', 'project generated successfully');
console.log('debug', `run '${chalk.bold('npm install')}' to install the dependencies`);
console.log('debug', `run '${chalk.bold('npm build')}' to compile the application`);
console.log('debug', `run '${chalk.bold('npm run dev')}' to start the application`);
console.log('debug', `run '${chalk.bold('npm test')}' to execute the unit tests`);
},
};
}

function generate(dir, template, data) {
return new Promise((resolve, reject) => {
Expand Down Expand Up @@ -51,7 +53,7 @@ export function cli(args) {
if (existsSync(join(dir, 'package.json'))) {
exit('a package.json file already exists in target directory');
}

let template = getTemplate(opts.appType);
generate(dir, template, opts).catch(function (err) {
if (err) {
console.error(err.message);
Expand Down
5 changes: 4 additions & 1 deletion packages/cli/src/parseArgs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ interface Args {
appPrefix: string;
appName: string;
healthcheckPath: string;
appType: string;
}

export default function (args): Args {
Expand All @@ -31,7 +32,8 @@ export default function (args): Args {
},
number: ['port', 'debug-port', 'plugin-timeout'],
boolean: ['debug', 'help'],
string: ['address', 'socket', 'debug-host', 'app-dir', 'app-prefix', 'app-name', 'healthcheck-path'],
string: ['address', 'socket', 'debug-host', 'app-dir', 'app-prefix', 'app-name', 'healthcheck-path',
'app-type'],
envPrefix: 'HOTH_',
alias: {
port: ['p'],
Expand Down Expand Up @@ -67,6 +69,7 @@ export default function (args): Args {
appPrefix: parsedArgs.appPrefix,
appName: parsedArgs.appName,
healthcheckPath: parsedArgs.healthcheckPath,
appType: parsedArgs.appType,
pluginOptions,
};
}
Loading

0 comments on commit 876dc3b

Please sign in to comment.