重构了后台启动的相关部分
This commit is contained in:
parent
066ff597e5
commit
f4b11e7fdf
|
|
@ -10,7 +10,7 @@ async function run(options) {
|
|||
(0, tip_style_1.Success)(`${(0, tip_style_1.success)('初始化数据库中……')}`);
|
||||
// ts-node scripts/build-app-domain & npm link ./app-domain
|
||||
const drop = options.args.includes('drop') || false;
|
||||
const result = cross_spawn_1.default.sync('ts-node', [require.resolve('../scripts/' + 'initialize-database.js'), `${drop}`], {
|
||||
const result = cross_spawn_1.default.sync('ts-node', [require.resolve('../scripts/' + 'initialize-server.ts'), `${drop}`], {
|
||||
stdio: 'inherit',
|
||||
shell: true,
|
||||
});
|
||||
|
|
@ -28,6 +28,7 @@ async function run(options) {
|
|||
// ts-node scripts/build-app-domain & npm link ./app-domain
|
||||
const result = cross_spawn_1.default.sync(`cross-env`, [
|
||||
`NODE_ENV=${options.mode}`,
|
||||
'OAK_PLATFORM=server',
|
||||
'ts-node',
|
||||
require.resolve('../scripts/' + 'start-server.js'),
|
||||
], {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
/// <reference path="../../src/typings/polyfill.d.ts" />
|
||||
import { Context, EntityDict, RowStore } from 'oak-domain/lib/types';
|
||||
export declare function initialize<ED extends EntityDict, Cxt extends Context<ED>>(path: string, contextBuilder: (scene?: string) => (store: RowStore<ED, Cxt>) => Cxt, dropIfExists?: boolean): Promise<void>;
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.initialize = void 0;
|
||||
/// <reference path="../typings/polyfill.d.ts" />
|
||||
const oak_backend_base_1 = require("oak-backend-base");
|
||||
async function initialize(path, contextBuilder, dropIfExists) {
|
||||
const appLoader = new oak_backend_base_1.AppLoader(path, contextBuilder);
|
||||
await appLoader.mount();
|
||||
await appLoader.initialize(dropIfExists);
|
||||
await appLoader.unmount();
|
||||
console.log('data initialized');
|
||||
}
|
||||
exports.initialize = initialize;
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
export declare type GenerateIdOption = {
|
||||
shuffle?: boolean;
|
||||
};
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const uuid_1 = require("uuid");
|
||||
async function generateNewId(option) {
|
||||
if (option?.shuffle && process.env.NODE_ENV === 'development') {
|
||||
return (0, uuid_1.v4)();
|
||||
}
|
||||
return (0, uuid_1.v1)();
|
||||
}
|
||||
Object.assign(global, {
|
||||
generateNewId,
|
||||
});
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
/// <reference path="../../src/typings/polyfill.d.ts" />
|
||||
import './polyfill';
|
||||
import { Connector, EntityDict, Context, RowStore } from 'oak-domain/lib/types';
|
||||
export declare function startup<ED extends EntityDict, Cxt extends Context<ED>>(path: string, contextBuilder: (scene?: string) => (store: RowStore<ED, Cxt>) => Cxt, connector: Connector<ED, Cxt>): Promise<void>;
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.startup = void 0;
|
||||
/// <reference path="../typings/polyfill.d.ts" />
|
||||
require("./polyfill");
|
||||
const koa_1 = __importDefault(require("koa"));
|
||||
const koa_router_1 = __importDefault(require("koa-router"));
|
||||
const koa_body_1 = __importDefault(require("koa-body"));
|
||||
const oak_backend_base_1 = require("oak-backend-base");
|
||||
const types_1 = require("oak-domain/lib/types");
|
||||
async function startup(path, contextBuilder, connector) {
|
||||
const appLoader = new oak_backend_base_1.AppLoader(path, contextBuilder);
|
||||
await appLoader.mount();
|
||||
const koa = new koa_1.default();
|
||||
koa.use((0, koa_body_1.default)({
|
||||
multipart: true,
|
||||
}));
|
||||
const router = new koa_router_1.default();
|
||||
// 如果是开发环境,允许options
|
||||
if (process.env.NODE_ENV = 'development') {
|
||||
koa.use(async (ctx, next) => {
|
||||
ctx.set('Access-Control-Allow-Origin', '*');
|
||||
ctx.set('Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With, oak-cxt, oak-aspect');
|
||||
ctx.set('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS');
|
||||
if (ctx.method == 'OPTIONS') {
|
||||
ctx.body = 200;
|
||||
}
|
||||
else {
|
||||
await next();
|
||||
}
|
||||
});
|
||||
}
|
||||
router.post(connector.getRouter(), async (ctx) => {
|
||||
console.log('aspect called');
|
||||
const { request } = ctx;
|
||||
const { name, params, context } = connector.parseRequest(request.headers, request.body, appLoader.getStore());
|
||||
await context.begin();
|
||||
let result;
|
||||
try {
|
||||
result = await appLoader.execAspect(name, context, params);
|
||||
await context.commit();
|
||||
}
|
||||
catch (err) {
|
||||
await context.rollback();
|
||||
console.error(err);
|
||||
const exception = err instanceof types_1.OakException ? err : new types_1.OakException('内部不可知错误');
|
||||
const { body } = connector.serializeException(exception, request.headers, request.body);
|
||||
ctx.response.body = body;
|
||||
return;
|
||||
}
|
||||
const { body, headers } = connector.serializeResult(result, context, request.headers, request.body);
|
||||
ctx.response.body = body;
|
||||
return;
|
||||
});
|
||||
koa.use(router.routes());
|
||||
const serverConfig = require(`${path}/configuration/server.json`);
|
||||
console.log(`server will listen on port ${serverConfig.port}`);
|
||||
koa.on('error', (err) => {
|
||||
console.error(err);
|
||||
throw err;
|
||||
});
|
||||
koa.listen(serverConfig.port);
|
||||
}
|
||||
exports.startup = startup;
|
||||
11
package.json
11
package.json
|
|
@ -19,8 +19,10 @@
|
|||
"devDependencies": {
|
||||
"@types/cross-spawn": "^6.0.2",
|
||||
"@types/inquirer": "^7.3.1",
|
||||
"@types/koa-router": "^7.4.4",
|
||||
"@types/node": "^12.0.27",
|
||||
"@types/shelljs": "^0.8.8",
|
||||
"@types/uuid": "^8.3.4",
|
||||
"@xmldom/xmldom": "^0.8.2",
|
||||
"stream-browserify": "^3.0.0",
|
||||
"typescript": "^4.6.3"
|
||||
|
|
@ -66,17 +68,15 @@
|
|||
"jest": "^27.4.3",
|
||||
"jest-resolve": "^27.4.2",
|
||||
"jest-watch-typeahead": "^1.0.0",
|
||||
"koa": "^2.13.4",
|
||||
"koa-body": "^5.0.0",
|
||||
"koa-router": "^11.0.1",
|
||||
"less": "^4.1.2",
|
||||
"less-loader": "^10.2.0",
|
||||
"loader-utils": "^3.2.0",
|
||||
"lodash": "^4.17.21",
|
||||
"mini-css-extract-plugin": "^2.5.3",
|
||||
"oak-common-aspect": "file:../oak-common-aspect",
|
||||
"oak-domain": "file:../oak-domain",
|
||||
"oak-external-sdk": "file:../oak-external-sdk",
|
||||
"oak-frontend-base": "file:../oak-frontend-base",
|
||||
"oak-general-business": "file:../oak-general-business",
|
||||
"oak-memory-tree-store": "file:../oak-memory-tree-store",
|
||||
"postcss": "^8.4.4",
|
||||
"postcss-flexbugs-fixes": "^5.0.2",
|
||||
"postcss-less": "^6.0.0",
|
||||
|
|
@ -100,6 +100,7 @@
|
|||
"tailwindcss": "^3.0.2",
|
||||
"terser-webpack-plugin": "^5.2.5",
|
||||
"ui-extract-webpack-plugin": "^1.0.0",
|
||||
"uuid": "^8.3.2",
|
||||
"webpack": "^5.72.0",
|
||||
"webpack-dev-server": "^4.6.0",
|
||||
"webpack-manifest-plugin": "^4.0.2",
|
||||
|
|
|
|||
|
|
@ -1,9 +0,0 @@
|
|||
const { initialize } = require('oak-backend-base');
|
||||
const pwd = process.cwd();
|
||||
|
||||
const dropIfExists = process.argv[2];
|
||||
|
||||
initialize(pwd, dropIfExists)
|
||||
.then(
|
||||
() => process.exit(0)
|
||||
);
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
const { startup } = require('oak-backend-base');
|
||||
const pwd = process.cwd();
|
||||
|
||||
startup(pwd);
|
||||
|
|
@ -15,7 +15,7 @@ export default async function run(options: any): Promise<void> {
|
|||
const drop = options.args.includes('drop') || false;
|
||||
const result = spawn.sync(
|
||||
'ts-node',
|
||||
[require.resolve('../scripts/' + 'initialize-database.js'), `${drop}`],
|
||||
[require.resolve('../scripts/' + 'initialize-server.ts'), `${drop}`],
|
||||
{
|
||||
stdio: 'inherit',
|
||||
shell: true,
|
||||
|
|
@ -37,6 +37,7 @@ export default async function run(options: any): Promise<void> {
|
|||
`cross-env`,
|
||||
[
|
||||
`NODE_ENV=${options.mode}`,
|
||||
'OAK_PLATFORM=server',
|
||||
'ts-node',
|
||||
require.resolve('../scripts/' + 'start-server.js'),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
/// <reference path="../typings/polyfill.d.ts" />
|
||||
import { AppLoader } from 'oak-backend-base';
|
||||
import { Context, EntityDict, RowStore } from 'oak-domain/lib/types';
|
||||
|
||||
export async function initialize<ED extends EntityDict, Cxt extends Context<ED>>(path: string, contextBuilder: (scene?: string) => (store: RowStore<ED, Cxt>) => Cxt, dropIfExists?: boolean) {
|
||||
const appLoader = new AppLoader(path, contextBuilder);
|
||||
await appLoader.mount();
|
||||
await appLoader.initialize(dropIfExists);
|
||||
await appLoader.unmount();
|
||||
console.log('data initialized');
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
import { v4, v1 } from 'uuid';
|
||||
|
||||
export type GenerateIdOption = {
|
||||
shuffle?: boolean;
|
||||
};
|
||||
|
||||
async function generateNewId(option?: GenerateIdOption) {
|
||||
if (option?.shuffle && process.env.NODE_ENV === 'development') {
|
||||
return v4();
|
||||
}
|
||||
return v1();
|
||||
}
|
||||
|
||||
Object.assign(global, {
|
||||
generateNewId,
|
||||
});
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
/// <reference path="../typings/polyfill.d.ts" />
|
||||
import './polyfill';
|
||||
import Koa from 'koa';
|
||||
import KoaRouter from 'koa-router';
|
||||
import KoaBody from 'koa-body';
|
||||
import { AppLoader, BackendContext } from 'oak-backend-base';
|
||||
import { OakException, Connector, EntityDict, Context, RowStore } from 'oak-domain/lib/types';
|
||||
|
||||
export async function startup<ED extends EntityDict, Cxt extends Context<ED>>(path: string, contextBuilder: (scene?: string) => (store: RowStore<ED, Cxt>) => Cxt, connector: Connector<ED, Cxt>) {
|
||||
const appLoader = new AppLoader(path, contextBuilder);
|
||||
await appLoader.mount();
|
||||
const koa = new Koa();
|
||||
koa.use(KoaBody({
|
||||
multipart: true,
|
||||
}));
|
||||
const router = new KoaRouter();
|
||||
|
||||
// 如果是开发环境,允许options
|
||||
if (process.env.NODE_ENV = 'development') {
|
||||
koa.use(async (ctx, next) => {
|
||||
ctx.set('Access-Control-Allow-Origin', '*');
|
||||
ctx.set('Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With, oak-cxt, oak-aspect');
|
||||
ctx.set('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS');
|
||||
if (ctx.method == 'OPTIONS') {
|
||||
ctx.body = 200;
|
||||
} else {
|
||||
await next();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
router.post(connector.getRouter(), async (ctx) => {
|
||||
console.log('aspect called');
|
||||
const { request } = ctx;
|
||||
const { name, params, context } = connector.parseRequest(request.headers, request.body, appLoader.getStore());
|
||||
await context.begin();
|
||||
let result: any;
|
||||
try {
|
||||
result = await appLoader.execAspect(name, context, params);
|
||||
await context.commit();
|
||||
}
|
||||
catch (err: any) {
|
||||
await context.rollback();
|
||||
console.error(err);
|
||||
const exception = err instanceof OakException ? err : new OakException('内部不可知错误');
|
||||
const { body } = connector.serializeException(exception, request.headers, request.body);
|
||||
ctx.response.body = body;
|
||||
return;
|
||||
}
|
||||
const { body, headers } = connector.serializeResult(result, context, request.headers, request.body);
|
||||
ctx.response.body = body;
|
||||
return;
|
||||
});
|
||||
koa.use(router.routes());
|
||||
|
||||
|
||||
const serverConfig = require(`${path}/configuration/server.json`);
|
||||
console.log(`server will listen on port ${serverConfig.port}`);
|
||||
koa.on('error', (err) => {
|
||||
console.error(err);
|
||||
throw err;
|
||||
});
|
||||
koa.listen(serverConfig.port);
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
import { GenerateIdOption } from "oak-backend-base/src/polyfill";
|
||||
|
||||
declare global {
|
||||
const generateNewId: (option?: GenerateIdOption) => Promise<string>;
|
||||
const __DEV__: boolean;
|
||||
}
|
||||
export {}
|
||||
|
|
@ -62,7 +62,8 @@
|
|||
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
|
||||
/* Advanced Options */
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"resolveJsonModule": true /* Disallow inconsistently-cased references to the same file. */
|
||||
"resolveJsonModule": true, /* Disallow inconsistently-cased references to the same file. */
|
||||
"experimentalDecorators": true
|
||||
},
|
||||
"include": [ "src/**/*" ],
|
||||
"exclude": [
|
||||
|
|
|
|||
Loading…
Reference in New Issue