diff --git a/lib/server/start.js b/lib/server/start.js index 555c73c..fded2be 100644 --- a/lib/server/start.js +++ b/lib/server/start.js @@ -200,7 +200,7 @@ async function startup(path, connector, omitWatchers, omitTimers, routine) { catch (err) { console.error(err); const { request } = ctx; - const exception = err instanceof types_1.OakException + const exception = (0, types_1.isOakException)(err) ? err : new types_1.OakException(serverConfiguration?.internalExceptionMask || ExceptionMask); @@ -236,6 +236,10 @@ async function startup(path, connector, omitWatchers, omitTimers, routine) { ctx.set('Access-Control-Allow-Origin', '*'); ctx.set('Access-Control-Allow-Headers', corsHeaders.concat(connector.getCorsHeader())); ctx.set('Access-Control-Allow-Methods', corsMethods); + if (connector.getCorsExposeHeaders) { + const exposeHeaders = connector.getCorsExposeHeaders(); + ctx.set('Access-Control-Expose-Headers', exposeHeaders); + } if (ctx.method == 'OPTIONS') { ctx.body = 200; } @@ -269,12 +273,39 @@ async function startup(path, connector, omitWatchers, omitTimers, routine) { } }); } + const connectorCustomAspects = connector.registerCustomAspect ? connector.registerCustomAspect() : null; router.post(connector.getRouter(), async (ctx) => { const { request } = ctx; - const { contextString, aspectName, data } = connector.parseRequest(request.headers, request.body, request.files); - const { result, opRecords, message } = await appLoader.execAspect(aspectName, request.headers, contextString, data); + const { contextString, aspectName, data } = await connector.parseRequest(request.headers, request.body, request.files); + let result; + let opRecords = []; + let message = undefined; + if (connectorCustomAspects && + connectorCustomAspects.findIndex(a => a.name === aspectName) >= 0) { + // 自定义aspect处理 + console.log(`调用Connector自定义Aspect: ${aspectName}`); + const aspect = connectorCustomAspects.find(a => a.name === aspectName); + const res = await aspect.handler({ + headers: request.headers, + contextString, + params: data, + }); + result = res.result; + opRecords = res.opRecords || []; + message = res.message; + } + else { + const res = await appLoader.execAspect(aspectName, request.headers, contextString, data); + result = res.result; + opRecords = res.opRecords || []; + message = res.message; + } const { body, headers } = await connector.serializeResult(result, opRecords, request.headers, request.body, message); ctx.response.body = body; + // headers 要拼上 + Object.keys(headers || {}).forEach(key => { + ctx.set(key, headers?.[key]); + }); return; }); // 桥接访问外部资源的入口 diff --git a/lib/server/watch.js b/lib/server/watch.js index c801260..d0dae67 100644 --- a/lib/server/watch.js +++ b/lib/server/watch.js @@ -280,11 +280,12 @@ const createCompiler = async (projectPath, options, projectReferences, treatFile }; const compileTask = async (task) => { const { filePath, changeType } = task; + const modulePath = path_1.default.resolve(filePath); // 判断文件类型 if (!filePath.endsWith(".ts")) { // 处理非TypeScript文件 (如JSON文件) if (filePath.endsWith(".json")) { - const targetPath = filePath.replace(path_1.default.join(projectPath, "src"), path_1.default.join(projectPath, "lib")); + const targetPath = modulePath.replace(path_1.default.join(projectPath, "src"), path_1.default.join(projectPath, "lib")); try { if (changeType === "remove") { if (fs_1.default.existsSync(targetPath)) { @@ -331,7 +332,6 @@ const createCompiler = async (projectPath, options, projectReferences, treatFile // 处理TypeScript文件 console.clear(); console.warn(`File ${filePath} has been ${changeType}d`); - const modulePath = path_1.default.resolve(filePath); const libPath = modulePath .replace(path_1.default.join(projectPath, "src"), path_1.default.join(projectPath, "lib")) .replace(/\.ts$/, ".js"); diff --git a/lib/template.js b/lib/template.js index b1d2bfc..610982d 100644 --- a/lib/template.js +++ b/lib/template.js @@ -85,7 +85,7 @@ function packageJsonContent({ name, version, description, cliName, cliBinName, i "build-analyze:mp:staging": "${cliBinName} build --target mp --mode staging --analyze", "build:mp": "${cliBinName} build --target mp --mode production", "build-analyze:mp": "${cliBinName} build --target mp --mode production --analyze", - "build:watch": "tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json && npm run copy-config-json && npm run server:start:watch", + "build:watch": "node --stack-size=4096 ./scripts/build.js -p tsconfig.build.json && tsc-alias -p tsconfig.build.json && npm run copy-config-json && npm run server:start:watch", "start:web": "${cliBinName} start --target web --mode development --devMode frontend", "start:web:server": "${cliBinName} start --target web --mode development", "start:native": "${cliBinName} start --target rn --mode development --devMode frontend", @@ -97,7 +97,7 @@ function packageJsonContent({ name, version, description, cliName, cliBinName, i "build-sourcemap:web": "${cliBinName} build --target web --mode production --sourcemap", "build-analyze:web": "${cliBinName} build --target web --mode production --analyze", "build-sourcemap-analyze:web": "${cliBinName} build --target web --mode production --sourcemap --analyze", - "build": "tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json && npm run copy-config-json", + "build": "node --stack-size=4096 ./scripts/build.js -p tsconfig.build.json && tsc-alias -p tsconfig.build.json && npm run copy-config-json", "prebuild": "npm run make:locale", "run:ios": "oak-cli run -p ios", "run:android": "oak-cli run -p android", @@ -397,7 +397,13 @@ function tsConfigBuildJsonContent() { "test", "src/pages/**/*", "src/components/**/*" - ] + ], + "oakBuildChecks": { + "context": { + "checkAsyncContext": true, + "targetModules": ["context/BackendRuntimeContext"] + } + } }`; } function tsConfigPathsJsonContent(deps) { diff --git a/package.json b/package.json index c6a87c3..ba22a17 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@xuchangzju/oak-cli", - "version": "4.0.30", + "version": "4.0.31", "description": "client for oak framework", "main": "lib/index.js", "scripts": { @@ -112,9 +112,9 @@ "lodash": "^4.17.21", "mini-css-extract-plugin": "^2.5.3", "node-watch": "^0.7.4", - "oak-backend-base": "^4.1.25", - "oak-domain": "^5.1.31", - "oak-frontend-base": "^5.3.43", + "oak-backend-base": "^4.1.26", + "oak-domain": "^5.1.33", + "oak-frontend-base": "^5.3.45", "parse-asn1": "5.1.6", "postcss": "^8.4.4", "postcss-flexbugs-fixes": "^5.0.2", diff --git a/src/server/start.ts b/src/server/start.ts index 4cb3992..126bcd9 100644 --- a/src/server/start.ts +++ b/src/server/start.ts @@ -9,7 +9,7 @@ import KoaBody from 'koa-body'; import { AppLoader, getClusterInfo, ClusterAppLoader } from 'oak-backend-base'; import { BackendRuntimeContext } from 'oak-frontend-base/lib/context/BackendRuntimeContext'; -import { OakException, Connector, EntityDict, ClusterInfo } from 'oak-domain/lib/types'; +import { OakException, Connector, EntityDict, ClusterInfo, OpRecord, isOakException } from 'oak-domain/lib/types'; import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain'; import { AsyncRowStore, AsyncContext } from 'oak-domain/lib/store/AsyncRowStore'; import { SyncContext } from 'oak-domain/lib/store/SyncRowStore'; @@ -245,7 +245,7 @@ export async function startup( serverConfiguration?.internalExceptionMask || @@ -260,11 +260,13 @@ export async function startup { const { request } = ctx; - const { contextString, aspectName, data } = connector.parseRequest( + const { contextString, aspectName, data } = await connector.parseRequest( request.headers, request.body, request.files ); - const { result, opRecords, message } = await appLoader.execAspect( - aspectName, - request.headers, - contextString, - data - ); + let result: any; + let opRecords: OpRecord[] = []; + let message: string | undefined = undefined; + + if (connectorCustomAspects && + connectorCustomAspects.findIndex(a => a.name === aspectName) >= 0 + ) { + // 自定义aspect处理 + console.log(`调用Connector自定义Aspect: ${aspectName}`); + const aspect = connectorCustomAspects!.find(a => a.name === aspectName)!; + const res = await aspect.handler( + { + headers: request.headers, + contextString, + params: data, + } + ); + result = res.result; + opRecords = res.opRecords || []; + message = res.message; + } else { + const res = await appLoader.execAspect( + aspectName, + request.headers, + contextString, + data + ); + result = res.result; + opRecords = res.opRecords || []; + message = res.message; + } + const { body, headers } = await connector.serializeResult( result, opRecords, @@ -350,6 +384,12 @@ export async function startup { + ctx.set(key, headers?.[key]) + }) + return; }); @@ -519,15 +559,15 @@ export async function startup => { const { filePath, changeType } = task; + const modulePath = pathLib.resolve(filePath); // 判断文件类型 if (!filePath.endsWith(".ts")) { // 处理非TypeScript文件 (如JSON文件) if (filePath.endsWith(".json")) { - const targetPath = filePath.replace( + const targetPath = modulePath.replace( pathLib.join(projectPath, "src"), pathLib.join(projectPath, "lib") ); @@ -533,7 +534,6 @@ const createCompiler = async ( console.clear(); console.warn(`File ${filePath} has been ${changeType}d`); - const modulePath = pathLib.resolve(filePath); const libPath = modulePath .replace(pathLib.join(projectPath, "src"), pathLib.join(projectPath, "lib")) .replace(/\.ts$/, ".js"); diff --git a/src/template.ts b/src/template.ts index 61fb3c6..abe7f88 100644 --- a/src/template.ts +++ b/src/template.ts @@ -92,7 +92,7 @@ export function packageJsonContent({ "build-analyze:mp:staging": "${cliBinName} build --target mp --mode staging --analyze", "build:mp": "${cliBinName} build --target mp --mode production", "build-analyze:mp": "${cliBinName} build --target mp --mode production --analyze", - "build:watch": "tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json && npm run copy-config-json && npm run server:start:watch", + "build:watch": "node --stack-size=4096 ./scripts/build.js -p tsconfig.build.json && tsc-alias -p tsconfig.build.json && npm run copy-config-json && npm run server:start:watch", "start:web": "${cliBinName} start --target web --mode development --devMode frontend", "start:web:server": "${cliBinName} start --target web --mode development", "start:native": "${cliBinName} start --target rn --mode development --devMode frontend", @@ -104,7 +104,7 @@ export function packageJsonContent({ "build-sourcemap:web": "${cliBinName} build --target web --mode production --sourcemap", "build-analyze:web": "${cliBinName} build --target web --mode production --analyze", "build-sourcemap-analyze:web": "${cliBinName} build --target web --mode production --sourcemap --analyze", - "build": "tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json && npm run copy-config-json", + "build": "node --stack-size=4096 ./scripts/build.js -p tsconfig.build.json && tsc-alias -p tsconfig.build.json && npm run copy-config-json", "prebuild": "npm run make:locale", "run:ios": "oak-cli run -p ios", "run:android": "oak-cli run -p android", @@ -406,7 +406,13 @@ export function tsConfigBuildJsonContent() { "test", "src/pages/**/*", "src/components/**/*" - ] + ], + "oakBuildChecks": { + "context": { + "checkAsyncContext": true, + "targetModules": ["context/BackendRuntimeContext"] + } + } }`; } diff --git a/template/scripts/build.js b/template/scripts/build.js new file mode 100644 index 0000000..5907633 --- /dev/null +++ b/template/scripts/build.js @@ -0,0 +1,6 @@ +/* eslint-disable @typescript-eslint/no-require-imports */ +const { build } = require('oak-domain/lib/compiler/tscBuilder.js') + +const pwd = process.cwd(); + +build(pwd, process.argv); \ No newline at end of file