Merge branch 'release'
This commit is contained in:
commit
3e2b2b10a4
|
|
@ -574,7 +574,7 @@ function outputIntializeDev(cwd, dependencies, briefNames, sourceFile, printer,
|
|||
* @param printer
|
||||
* @param filename
|
||||
*/
|
||||
function outputFeatureIndex(dependencies, briefNames, sourceFile, printer, filename) {
|
||||
function outputFeatureIndex(dependencies, briefNames, sourceFile, printer, filename, isModule) {
|
||||
const { statements } = sourceFile;
|
||||
let statements2 = [];
|
||||
if (dependencies.length > 0) {
|
||||
|
|
@ -605,6 +605,20 @@ function outputFeatureIndex(dependencies, briefNames, sourceFile, printer, filen
|
|||
...importStatements,
|
||||
...statements.slice(5)
|
||||
];
|
||||
if (isModule) {
|
||||
statements2.push(factory.createFunctionDeclaration([
|
||||
factory.createToken(ts.SyntaxKind.ExportKeyword),
|
||||
factory.createToken(ts.SyntaxKind.AsyncKeyword)
|
||||
], undefined, factory.createIdentifier("initialize"), [
|
||||
factory.createTypeParameterDeclaration(undefined, factory.createIdentifier("ED"), factory.createTypeReferenceNode(factory.createIdentifier("EntityDict"), undefined), undefined)
|
||||
], [
|
||||
factory.createParameterDeclaration(undefined, undefined, factory.createIdentifier("features"), undefined, factory.createIntersectionTypeNode([
|
||||
factory.createTypeReferenceNode(factory.createIdentifier("FeatureDict"), [factory.createTypeReferenceNode(factory.createIdentifier("ED"), undefined)]),
|
||||
factory.createTypeReferenceNode(factory.createIdentifier("BasicFeatures"), [factory.createTypeReferenceNode(factory.createIdentifier("ED"), undefined)]),
|
||||
...briefNames.map((ele) => factory.createTypeReferenceNode(factory.createIdentifier(`${(0, string_1.firstLetterUpperCase)(ele)}FeatureDict`), [factory.createTypeReferenceNode(factory.createIdentifier("ED"), undefined)]))
|
||||
]), undefined)
|
||||
], undefined, factory.createBlock([], true)));
|
||||
}
|
||||
}
|
||||
else {
|
||||
statements2 = [...statements];
|
||||
|
|
@ -786,12 +800,47 @@ function tryCopyModuleTemplateFiles(cwd, dependencies, briefNames, printer) {
|
|||
injectDataIndexFile(join(cwd, 'src', 'data', 'index.ts'), injectDataIndexFileBriefNames, printer);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 对于module类型的项目,在feature/index.ts中注入initialize函数
|
||||
* @param cwd
|
||||
* @param dependencies
|
||||
* @param briefNames
|
||||
*/
|
||||
function injectInitializeToFeatureIndex(cwd, dependencies, briefNames, printer) {
|
||||
const featureIndexFile = join(cwd, 'src', 'features', 'index.ts');
|
||||
const sourceFile = ts.createSourceFile('index.ts', (0, fs_1.readFileSync)(featureIndexFile, 'utf-8'), ts.ScriptTarget.Latest, false, ts.ScriptKind.TS);
|
||||
const { statements } = sourceFile;
|
||||
const initializeStmt = statements.find((stmt) => ts.isFunctionDeclaration(stmt) && ts.isIdentifier(stmt.name) && stmt.name.text === 'initialize');
|
||||
if (!initializeStmt) {
|
||||
const statements2 = [
|
||||
...(dependencies.map((dep, idx) => factory.createImportDeclaration(undefined, factory.createImportClause(false, undefined, factory.createNamedImports([factory.createImportSpecifier(false, factory.createIdentifier("FeatureDict"), factory.createIdentifier(`${(0, string_1.firstLetterUpperCase)(briefNames[idx])}FeatureDict`))])), factory.createStringLiteral(dep), undefined))),
|
||||
...statements,
|
||||
factory.createFunctionDeclaration([
|
||||
factory.createToken(ts.SyntaxKind.ExportKeyword),
|
||||
factory.createToken(ts.SyntaxKind.AsyncKeyword)
|
||||
], undefined, factory.createIdentifier("initialize"), [
|
||||
factory.createTypeParameterDeclaration(undefined, factory.createIdentifier("ED"), factory.createTypeReferenceNode(factory.createIdentifier("EntityDict"), undefined), undefined)
|
||||
], [
|
||||
factory.createParameterDeclaration(undefined, undefined, factory.createIdentifier("features"), undefined, factory.createIntersectionTypeNode([
|
||||
factory.createTypeReferenceNode(factory.createIdentifier("FeatureDict"), [factory.createTypeReferenceNode(factory.createIdentifier("ED"), undefined)]),
|
||||
factory.createTypeReferenceNode(factory.createIdentifier("BasicFeatures"), [factory.createTypeReferenceNode(factory.createIdentifier("ED"), undefined)]),
|
||||
...briefNames.map((ele) => factory.createTypeReferenceNode(factory.createIdentifier(`${(0, string_1.firstLetterUpperCase)(ele)}FeatureDict`), [factory.createTypeReferenceNode(factory.createIdentifier("ED"), undefined)]))
|
||||
]), undefined)
|
||||
], undefined, factory.createBlock([], true))
|
||||
];
|
||||
const result = printer.printList(ts.ListFormat.SourceFileStatements, factory.createNodeArray(statements2), sourceFile);
|
||||
(0, fs_1.writeFileSync)(featureIndexFile, result, { flag: 'w' });
|
||||
console.log(`注入${featureIndexFile}文件成功,用户可以自己修正initialize函数的参数和逻辑`);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 本函数用于构建src/initialize.dev, src/initialize.prod, src/initializeFeatures, src/context/FrontendContext, src/contextBackendContext
|
||||
* 这些和dependency相关的项目文件
|
||||
*/
|
||||
function buildDependency(rebuild) {
|
||||
const cwd = process.cwd();
|
||||
const webDir = join(cwd, 'web');
|
||||
const isModule = !(0, fs_1.existsSync)(webDir); // 如果没有web目录,说明是module,不需要处理模块级别的文件注入
|
||||
const depConfigFile = join(cwd, 'src', 'configuration', 'dependency.ts');
|
||||
if (!(0, fs_1.existsSync)(depConfigFile)) {
|
||||
console.error(`${depConfigFile}不存在,无法构建启动文件`);
|
||||
|
|
@ -801,8 +850,8 @@ function buildDependency(rebuild) {
|
|||
const dependencies = depGraph.ascOrder;
|
||||
const briefNames = dependencies.map((dep, idx) => `${dep.split('-').map(ele => ele[0]).join('')}${idx}`);
|
||||
const templateFileList = [
|
||||
join(cwd, 'node_modules', env_1.OAK_CLI_MODULE_NAME, 'templateFiles', 'initialize.dev.ts'),
|
||||
join(cwd, 'node_modules', env_1.OAK_CLI_MODULE_NAME, 'templateFiles', 'initialize.prod.ts'),
|
||||
join(cwd, 'node_modules', env_1.OAK_CLI_MODULE_NAME, 'templateFiles', 'initialize.frontend.ts'),
|
||||
join(cwd, 'node_modules', env_1.OAK_CLI_MODULE_NAME, 'templateFiles', 'initialize.server.ts'),
|
||||
join(cwd, 'node_modules', env_1.OAK_CLI_MODULE_NAME, 'templateFiles', 'initializeFeatures.ts'),
|
||||
join(cwd, 'node_modules', env_1.OAK_CLI_MODULE_NAME, 'templateFiles', 'RuntimeCxt.ts'),
|
||||
join(cwd, 'node_modules', env_1.OAK_CLI_MODULE_NAME, 'templateFiles', 'DependentExceptions.ts'),
|
||||
|
|
@ -811,26 +860,28 @@ function buildDependency(rebuild) {
|
|||
];
|
||||
const program = ts.createProgram(templateFileList, {});
|
||||
const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });
|
||||
const initDevFile = join(cwd, 'src', 'initialize.dev.ts');
|
||||
if ((0, fs_1.existsSync)(initDevFile) && !rebuild) {
|
||||
console.log(`[${initDevFile}]文件已经存在,无需构建启动文件`);
|
||||
}
|
||||
else {
|
||||
outputIntializeDev(cwd, dependencies, briefNames, program.getSourceFile(templateFileList[0]), printer, initDevFile);
|
||||
}
|
||||
const initProdFile = join(cwd, 'src', 'initialize.prod.ts');
|
||||
if ((0, fs_1.existsSync)(initProdFile) && !rebuild) {
|
||||
console.log(`[${initProdFile}]文件已经存在,无需构建启动文件`);
|
||||
}
|
||||
else {
|
||||
outputIntializeProd(cwd, dependencies, briefNames, program.getSourceFile(templateFileList[1]), printer, initProdFile);
|
||||
}
|
||||
const initFeaturesFile = join(cwd, 'src', 'initializeFeatures.ts');
|
||||
if ((0, fs_1.existsSync)(initFeaturesFile) && !rebuild) {
|
||||
console.log(`[${initFeaturesFile}]文件已经存在,无需构建启动文件`);
|
||||
}
|
||||
else {
|
||||
outputIntializeFeatures(cwd, dependencies, briefNames, program.getSourceFile(templateFileList[2]), printer, initFeaturesFile);
|
||||
if (!isModule) {
|
||||
const initDevFile = join(cwd, 'src', 'initialize.frontend.ts');
|
||||
if ((0, fs_1.existsSync)(initDevFile) && !rebuild) {
|
||||
console.log(`[${initDevFile}]文件已经存在,无需构建启动文件`);
|
||||
}
|
||||
else {
|
||||
outputIntializeDev(cwd, dependencies, briefNames, program.getSourceFile(templateFileList[0]), printer, initDevFile);
|
||||
}
|
||||
const initProdFile = join(cwd, 'src', 'initialize.server.ts');
|
||||
if ((0, fs_1.existsSync)(initProdFile) && !rebuild) {
|
||||
console.log(`[${initProdFile}]文件已经存在,无需构建启动文件`);
|
||||
}
|
||||
else {
|
||||
outputIntializeProd(cwd, dependencies, briefNames, program.getSourceFile(templateFileList[1]), printer, initProdFile);
|
||||
}
|
||||
const initFeaturesFile = join(cwd, 'src', 'initializeFeatures.ts');
|
||||
if ((0, fs_1.existsSync)(initFeaturesFile) && !rebuild) {
|
||||
console.log(`[${initFeaturesFile}]文件已经存在,无需构建启动文件`);
|
||||
}
|
||||
else {
|
||||
outputIntializeFeatures(cwd, dependencies, briefNames, program.getSourceFile(templateFileList[2]), printer, initFeaturesFile);
|
||||
}
|
||||
}
|
||||
const dependentContextFile = join(cwd, 'src', 'context', 'DependentContext.ts');
|
||||
if ((0, fs_1.existsSync)(dependentContextFile) && !rebuild) {
|
||||
|
|
@ -865,9 +916,11 @@ function buildDependency(rebuild) {
|
|||
console.log(`[${featureIndexFile}]文件已经存在,无需构建启动文件`);
|
||||
}
|
||||
else {
|
||||
outputFeatureIndex(dependencies, briefNames, program.getSourceFile(templateFileList[6]), printer, featureIndexFile);
|
||||
outputFeatureIndex(dependencies, briefNames, program.getSourceFile(templateFileList[6]), printer, featureIndexFile, isModule);
|
||||
}
|
||||
// 把各个依赖项目的一些初始化的文件拷贝过去
|
||||
tryCopyModuleTemplateFiles(cwd, dependencies, briefNames, printer);
|
||||
if (!isModule) {
|
||||
tryCopyModuleTemplateFiles(cwd, dependencies, briefNames, printer);
|
||||
}
|
||||
}
|
||||
exports.default = buildDependency;
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ export declare abstract class AsyncContext<ED extends EntityDict> implements Con
|
|||
opResult: OperationResult<ED>;
|
||||
private message?;
|
||||
events: {
|
||||
commit: Array<() => Promise<void>>;
|
||||
rollback: Array<() => Promise<void>>;
|
||||
commit: Array<(records: OpRecord<ED>[], cxtStr: string) => Promise<void>>;
|
||||
rollback: Array<(records: OpRecord<ED>[], cxtStr: string) => Promise<void>>;
|
||||
};
|
||||
/**
|
||||
* 在返回结果前调用,对数据行进行一些预处理,比如将一些敏感的列隐藏
|
||||
|
|
@ -27,7 +27,7 @@ export declare abstract class AsyncContext<ED extends EntityDict> implements Con
|
|||
getScene(): string | undefined;
|
||||
setScene(scene?: string): void;
|
||||
private resetEvents;
|
||||
on(event: 'commit' | 'rollback', callback: () => Promise<void>): void;
|
||||
on(event: 'commit' | 'rollback', callback: (records: OpRecord<ED>[], cxtStr: string) => Promise<void>): void;
|
||||
saveOpRecord<T extends keyof ED>(entity: T, operation: ED[T]['Operation']): void;
|
||||
/**
|
||||
* 一个context中不应该有并发的事务,这里将事务串行化,使用的时候千万要注意不要自己等自己
|
||||
|
|
|
|||
|
|
@ -119,9 +119,12 @@ class AsyncContext {
|
|||
if (this.uuid) {
|
||||
await this.rowStore.commit(this.uuid);
|
||||
const { commit: commitEvents } = this.events;
|
||||
for (const e of commitEvents) {
|
||||
/* for (const e of commitEvents) {
|
||||
await e();
|
||||
}
|
||||
} */
|
||||
// 提交时不能等在跨事务trigger上
|
||||
const cxtStr = await this.toString();
|
||||
commitEvents.forEach(evt => evt(this.opRecords, cxtStr));
|
||||
this.uuid = undefined;
|
||||
this.resetEvents();
|
||||
this.opRecords = [];
|
||||
|
|
@ -133,9 +136,9 @@ class AsyncContext {
|
|||
if (this.uuid) {
|
||||
await this.rowStore.rollback(this.uuid);
|
||||
const { rollback: rollbackEvents } = this.events;
|
||||
for (const e of rollbackEvents) {
|
||||
await e();
|
||||
}
|
||||
// 回退时不能等在跨事务trigger上
|
||||
const cxtStr = await this.toString();
|
||||
rollbackEvents.forEach(evt => evt(this.opRecords, cxtStr));
|
||||
this.uuid = undefined;
|
||||
this.opRecords = [];
|
||||
this.opResult = {};
|
||||
|
|
|
|||
|
|
@ -221,19 +221,22 @@ class TriggerExecutor {
|
|||
}
|
||||
}
|
||||
postCommitTrigger(entity, operation, trigger, context, option) {
|
||||
context.on('commit', async () => {
|
||||
context.on('commit', async (opRecords, cxtStr) => {
|
||||
let ids = [];
|
||||
let cxtStr = await context.toString();
|
||||
const { opRecords } = context;
|
||||
let cxtStr2 = cxtStr;
|
||||
const { data } = operation;
|
||||
if (operation.action === 'create') {
|
||||
if (data instanceof Array) {
|
||||
ids = data.map(ele => ele.id);
|
||||
cxtStr = data[0].$$triggerData$$?.cxtStr || await context.toString();
|
||||
if (data[0].$$triggerData$$?.cxtStr) {
|
||||
cxtStr2 = data[0].$$triggerData$$?.cxtStr;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ids = [data.id];
|
||||
cxtStr = data.$$triggerData$$?.cxtStr || await context.toString();
|
||||
if (data.$$triggerData$$?.cxtStr) {
|
||||
cxtStr2 = data.$$triggerData$$?.cxtStr;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
@ -242,7 +245,9 @@ class TriggerExecutor {
|
|||
* 若trigger是takeEasy,只会在事务提交时做一次,使用当前context应也无大问题
|
||||
* 暂时先这样设计,若当前提交事务中改变了cxt内容,也许会有问题。by Xc 20240319
|
||||
*/
|
||||
cxtStr = data.$$triggerData$$?.cxtStr || await context.toString();
|
||||
if (data.$$triggerData$$?.cxtStr) {
|
||||
cxtStr2 = data.$$triggerData$$?.cxtStr;
|
||||
}
|
||||
const record = opRecords.find(ele => ele.id === operation.id);
|
||||
// 目前框架在operation时,一定会将ids记录在operation当中(见CascadeStore中的doUpdateSingleRowAsync函数
|
||||
(0, assert_1.default)(record && record.a !== 'c');
|
||||
|
|
@ -250,7 +255,7 @@ class TriggerExecutor {
|
|||
ids = f.id.$in;
|
||||
}
|
||||
// 此时项目的上下文,和执行此trigger时的上下文可能不一致(rootMode),采用当时的上下文cxtStr来执行
|
||||
this.onVolatileTrigger(entity, trigger, ids, cxtStr, option);
|
||||
this.onVolatileTrigger(entity, trigger, ids, cxtStr2, option);
|
||||
});
|
||||
}
|
||||
preOperation(entity, operation, context, option) {
|
||||
|
|
@ -335,6 +340,8 @@ class TriggerExecutor {
|
|||
const { fn } = trigger;
|
||||
const callback = await fn({ ids }, context, option);
|
||||
if (trigger.strict === 'makeSure') {
|
||||
// 这里开root模式,否则还可能有权限问题
|
||||
context.openRootMode();
|
||||
await context.operate(entity, {
|
||||
id: await (0, uuid_1.generateNewIdAsync)(),
|
||||
action: 'update',
|
||||
|
|
|
|||
|
|
@ -1,14 +1,12 @@
|
|||
import { AuthDeduceRelationMap, EntityDict } from './Entity';
|
||||
import { EntityDict as BaseEntityDict } from "../base-app-domain";
|
||||
import { AsyncContext } from '../store/AsyncRowStore';
|
||||
import { SyncConfig } from "./Sync";
|
||||
import { AttrUpdateMatrix } from './EntityDesc';
|
||||
import { ActionDefDict } from './Action';
|
||||
import { StyleDict } from './Style';
|
||||
/**
|
||||
* 后台配置
|
||||
*/
|
||||
export type ServerConfiguration<ED extends BaseEntityDict & EntityDict, Cxt extends AsyncContext<ED>> = {
|
||||
export type ServerConfiguration = {
|
||||
database: {
|
||||
type: 'mysql';
|
||||
host: string;
|
||||
|
|
@ -22,7 +20,20 @@ export type ServerConfiguration<ED extends BaseEntityDict & EntityDict, Cxt exte
|
|||
workDir: {
|
||||
path: string;
|
||||
};
|
||||
sync?: SyncConfig<ED, Cxt>;
|
||||
port: number;
|
||||
hostname: string;
|
||||
nginx?: {
|
||||
ssl: boolean;
|
||||
apiPath: string;
|
||||
port?: number;
|
||||
socketPath: string;
|
||||
};
|
||||
cors?: {
|
||||
origin: string;
|
||||
headers?: string[];
|
||||
methods?: string[];
|
||||
};
|
||||
internalExceptionMask?: string;
|
||||
};
|
||||
/**
|
||||
* 前后台访问配置
|
||||
|
|
|
|||
|
|
@ -351,83 +351,83 @@ function makeException(data) {
|
|||
break;
|
||||
}
|
||||
case 'OakUserException': {
|
||||
const e = new OakUserException(data.message);
|
||||
e = new OakUserException(data.message);
|
||||
break;
|
||||
}
|
||||
case 'OakRowInconsistencyException': {
|
||||
const e = new OakRowInconsistencyException(data.data, data.message);
|
||||
e = new OakRowInconsistencyException(data.data, data.message);
|
||||
break;
|
||||
}
|
||||
case 'OakInputIllegalException': {
|
||||
const e = new OakInputIllegalException(data.entity, data.attributes, data.message);
|
||||
e = new OakInputIllegalException(data.entity, data.attributes, data.message);
|
||||
break;
|
||||
}
|
||||
case 'OakAttrCantUpdateException': {
|
||||
const e = new OakAttrCantUpdateException(data.entity, data.attributes, data.message);
|
||||
e = new OakAttrCantUpdateException(data.entity, data.attributes, data.message);
|
||||
break;
|
||||
}
|
||||
case 'OakUserUnpermittedException': {
|
||||
const e = new OakUserUnpermittedException(data.entity, data.operation, data.message);
|
||||
e = new OakUserUnpermittedException(data.entity, data.operation, data.message);
|
||||
break;
|
||||
}
|
||||
case 'OakUserInvisibleException': {
|
||||
const e = new OakUserInvisibleException(data.entity, data.operation, data.message);
|
||||
e = new OakUserInvisibleException(data.entity, data.operation, data.message);
|
||||
break;
|
||||
}
|
||||
case 'OakUnloggedInException': {
|
||||
const e = new OakUnloggedInException(data.message);
|
||||
e = new OakUnloggedInException(data.message);
|
||||
break;
|
||||
}
|
||||
case 'OakCongruentRowExists': {
|
||||
const e = new OakCongruentRowExists(data.entity, data.data, data.message);
|
||||
e = new OakCongruentRowExists(data.entity, data.data, data.message);
|
||||
break;
|
||||
}
|
||||
case 'OakRowLockedException': {
|
||||
const e = new OakRowLockedException(data.message);
|
||||
e = new OakRowLockedException(data.message);
|
||||
break;
|
||||
}
|
||||
case 'OakRowUnexistedException': {
|
||||
const e = new OakRowUnexistedException(data.rows);
|
||||
e = new OakRowUnexistedException(data.rows);
|
||||
break;
|
||||
}
|
||||
case 'OakDeadlock': {
|
||||
const e = new OakDeadlock(data.message);
|
||||
e = new OakDeadlock(data.message);
|
||||
break;
|
||||
}
|
||||
case 'OakDataException': {
|
||||
const e = new OakDataException(data.message);
|
||||
e = new OakDataException(data.message);
|
||||
break;
|
||||
}
|
||||
case 'OakNoRelationDefException': {
|
||||
const e = new OakNoRelationDefException(data.entity, data.action, data.message);
|
||||
e = new OakNoRelationDefException(data.entity, data.action, data.message);
|
||||
break;
|
||||
}
|
||||
case 'OakUniqueViolationException': {
|
||||
const e = new OakUniqueViolationException(data.rows, data.message);
|
||||
e = new OakUniqueViolationException(data.rows, data.message);
|
||||
break;
|
||||
}
|
||||
case 'OakImportDataParseException': {
|
||||
const e = new OakImportDataParseException(data.message, data.line, data.header);
|
||||
e = new OakImportDataParseException(data.message, data.line, data.header);
|
||||
break;
|
||||
}
|
||||
case 'OakPreConditionUnsetException': {
|
||||
const e = new OakPreConditionUnsetException(data.message, data.entity, data.code);
|
||||
e = new OakPreConditionUnsetException(data.message, data.entity, data.code);
|
||||
break;
|
||||
}
|
||||
case 'OakAttrNotNullException': {
|
||||
const e = new OakAttrNotNullException(data.entity, data.attributes, data.message);
|
||||
e = new OakAttrNotNullException(data.entity, data.attributes, data.message);
|
||||
break;
|
||||
}
|
||||
case 'OakExternalException': {
|
||||
const e = new OakExternalException(data.source, data.code, data.message, data.data);
|
||||
e = new OakExternalException(data.source, data.code, data.message, data.data);
|
||||
break;
|
||||
}
|
||||
case 'OakNetworkException': {
|
||||
const e = new OakNetworkException(data.message);
|
||||
e = new OakNetworkException(data.message);
|
||||
break;
|
||||
}
|
||||
case 'OakServerProxyException': {
|
||||
const e = new OakServerProxyException(data.message);
|
||||
e = new OakServerProxyException(data.message);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -137,16 +137,9 @@ class SimpleConnector {
|
|||
const responseType = response.headers.get('Content-Type') ||
|
||||
response.headers.get('content-type');
|
||||
if (responseType?.toLocaleLowerCase().match(/application\/json/i)) {
|
||||
const { url, path, port, namespace } = await response.json();
|
||||
let url2 = url || this.serverUrl;
|
||||
if (port) {
|
||||
url2 += `:${port}`;
|
||||
}
|
||||
if (namespace) {
|
||||
url2 += namespace;
|
||||
}
|
||||
const { url, path } = await response.json();
|
||||
return {
|
||||
url: url2,
|
||||
url,
|
||||
path,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "oak-domain",
|
||||
"version": "5.0.0",
|
||||
"version": "5.0.1",
|
||||
"author": {
|
||||
"name": "XuChang"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1088,7 +1088,8 @@ function outputFeatureIndex(
|
|||
briefNames: string[],
|
||||
sourceFile: ts.SourceFile,
|
||||
printer: ts.Printer,
|
||||
filename: string
|
||||
filename: string,
|
||||
isModule: boolean,
|
||||
) {
|
||||
const { statements } = sourceFile;
|
||||
let statements2: ts.Statement[] = [];
|
||||
|
|
@ -1142,6 +1143,69 @@ function outputFeatureIndex(
|
|||
...importStatements,
|
||||
...statements.slice(5)
|
||||
];
|
||||
if (isModule) {
|
||||
statements2.push(
|
||||
factory.createFunctionDeclaration(
|
||||
[
|
||||
factory.createToken(ts.SyntaxKind.ExportKeyword),
|
||||
factory.createToken(ts.SyntaxKind.AsyncKeyword)
|
||||
],
|
||||
undefined,
|
||||
factory.createIdentifier("initialize"),
|
||||
[
|
||||
factory.createTypeParameterDeclaration(
|
||||
undefined,
|
||||
factory.createIdentifier("ED"),
|
||||
factory.createTypeReferenceNode(
|
||||
factory.createIdentifier("EntityDict"),
|
||||
undefined
|
||||
),
|
||||
undefined
|
||||
)
|
||||
],
|
||||
[
|
||||
factory.createParameterDeclaration(
|
||||
undefined,
|
||||
undefined,
|
||||
factory.createIdentifier("features"),
|
||||
undefined,
|
||||
factory.createIntersectionTypeNode([
|
||||
factory.createTypeReferenceNode(
|
||||
factory.createIdentifier("FeatureDict"),
|
||||
[factory.createTypeReferenceNode(
|
||||
factory.createIdentifier("ED"),
|
||||
undefined
|
||||
)]
|
||||
),
|
||||
factory.createTypeReferenceNode(
|
||||
factory.createIdentifier("BasicFeatures"),
|
||||
[factory.createTypeReferenceNode(
|
||||
factory.createIdentifier("ED"),
|
||||
undefined
|
||||
)]
|
||||
),
|
||||
...briefNames.map(
|
||||
(ele) => factory.createTypeReferenceNode(
|
||||
factory.createIdentifier(`${firstLetterUpperCase(ele)}FeatureDict`),
|
||||
[factory.createTypeReferenceNode(
|
||||
factory.createIdentifier("ED"),
|
||||
undefined
|
||||
)]
|
||||
)
|
||||
)
|
||||
|
||||
]),
|
||||
undefined
|
||||
)
|
||||
],
|
||||
undefined,
|
||||
factory.createBlock(
|
||||
[],
|
||||
true
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
statements2 = [...statements];
|
||||
|
|
@ -1305,7 +1369,7 @@ function outputIntializeFeatures(
|
|||
function injectDataIndexFile(
|
||||
dataIndexFile: string,
|
||||
briefNames: string[],
|
||||
printer: ts.Printer,
|
||||
printer: ts.Printer
|
||||
) {
|
||||
const sourceFile = ts.createSourceFile('index.ts', readFileSync(dataIndexFile, 'utf-8'), ts.ScriptTarget.Latest, false, ts.ScriptKind.TS);
|
||||
|
||||
|
|
@ -1457,6 +1521,121 @@ function tryCopyModuleTemplateFiles(
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 对于module类型的项目,在feature/index.ts中注入initialize函数
|
||||
* @param cwd
|
||||
* @param dependencies
|
||||
* @param briefNames
|
||||
*/
|
||||
function injectInitializeToFeatureIndex(
|
||||
cwd: string,
|
||||
dependencies: string[],
|
||||
briefNames: string[],
|
||||
printer: ts.Printer,
|
||||
) {
|
||||
const featureIndexFile = join(cwd, 'src', 'features', 'index.ts');
|
||||
|
||||
const sourceFile = ts.createSourceFile('index.ts', readFileSync(featureIndexFile, 'utf-8'), ts.ScriptTarget.Latest, false, ts.ScriptKind.TS);
|
||||
const { statements } = sourceFile;
|
||||
|
||||
const initializeStmt = statements.find(
|
||||
(stmt) => ts.isFunctionDeclaration(stmt) && ts.isIdentifier(stmt.name!) && stmt.name.text === 'initialize'
|
||||
);
|
||||
if (!initializeStmt) {
|
||||
const statements2 = [
|
||||
...(
|
||||
dependencies.map(
|
||||
(dep, idx) => factory.createImportDeclaration(
|
||||
undefined,
|
||||
factory.createImportClause(
|
||||
false,
|
||||
undefined,
|
||||
factory.createNamedImports(
|
||||
[factory.createImportSpecifier(
|
||||
false,
|
||||
factory.createIdentifier("FeatureDict"),
|
||||
factory.createIdentifier(`${firstLetterUpperCase(briefNames[idx])}FeatureDict`)
|
||||
)]
|
||||
)
|
||||
),
|
||||
factory.createStringLiteral(dep),
|
||||
undefined
|
||||
)
|
||||
|
||||
)
|
||||
),
|
||||
...statements,
|
||||
factory.createFunctionDeclaration(
|
||||
[
|
||||
factory.createToken(ts.SyntaxKind.ExportKeyword),
|
||||
factory.createToken(ts.SyntaxKind.AsyncKeyword)
|
||||
],
|
||||
undefined,
|
||||
factory.createIdentifier("initialize"),
|
||||
[
|
||||
factory.createTypeParameterDeclaration(
|
||||
undefined,
|
||||
factory.createIdentifier("ED"),
|
||||
factory.createTypeReferenceNode(
|
||||
factory.createIdentifier("EntityDict"),
|
||||
undefined
|
||||
),
|
||||
undefined
|
||||
)
|
||||
],
|
||||
[
|
||||
factory.createParameterDeclaration(
|
||||
undefined,
|
||||
undefined,
|
||||
factory.createIdentifier("features"),
|
||||
undefined,
|
||||
factory.createIntersectionTypeNode([
|
||||
factory.createTypeReferenceNode(
|
||||
factory.createIdentifier("FeatureDict"),
|
||||
[factory.createTypeReferenceNode(
|
||||
factory.createIdentifier("ED"),
|
||||
undefined
|
||||
)]
|
||||
),
|
||||
factory.createTypeReferenceNode(
|
||||
factory.createIdentifier("BasicFeatures"),
|
||||
[factory.createTypeReferenceNode(
|
||||
factory.createIdentifier("ED"),
|
||||
undefined
|
||||
)]
|
||||
),
|
||||
...briefNames.map(
|
||||
(ele) => factory.createTypeReferenceNode(
|
||||
factory.createIdentifier(`${firstLetterUpperCase(ele)}FeatureDict`),
|
||||
[factory.createTypeReferenceNode(
|
||||
factory.createIdentifier("ED"),
|
||||
undefined
|
||||
)]
|
||||
)
|
||||
)
|
||||
|
||||
]),
|
||||
undefined
|
||||
)
|
||||
],
|
||||
undefined,
|
||||
factory.createBlock(
|
||||
[],
|
||||
true
|
||||
)
|
||||
)
|
||||
];
|
||||
|
||||
const result = printer.printList(
|
||||
ts.ListFormat.SourceFileStatements,
|
||||
factory.createNodeArray(statements2),
|
||||
sourceFile);
|
||||
|
||||
writeFileSync(featureIndexFile, result, { flag: 'w' });
|
||||
console.log(`注入${featureIndexFile}文件成功,用户可以自己修正initialize函数的参数和逻辑`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 本函数用于构建src/initialize.dev, src/initialize.prod, src/initializeFeatures, src/context/FrontendContext, src/contextBackendContext
|
||||
* 这些和dependency相关的项目文件
|
||||
|
|
@ -1464,6 +1643,10 @@ function tryCopyModuleTemplateFiles(
|
|||
export default function buildDependency(rebuild?: boolean) {
|
||||
const cwd = process.cwd();
|
||||
|
||||
|
||||
const webDir = join(cwd, 'web');
|
||||
const isModule = !existsSync(webDir); // 如果没有web目录,说明是module,不需要处理模块级别的文件注入
|
||||
|
||||
const depConfigFile = join(cwd, 'src', 'configuration', 'dependency.ts');
|
||||
if (!existsSync(depConfigFile)) {
|
||||
console.error(`${depConfigFile}不存在,无法构建启动文件`);
|
||||
|
|
@ -1478,8 +1661,8 @@ export default function buildDependency(rebuild?: boolean) {
|
|||
);
|
||||
|
||||
const templateFileList = [
|
||||
join(cwd, 'node_modules', OAK_CLI_MODULE_NAME, 'templateFiles', 'initialize.dev.ts'),
|
||||
join(cwd, 'node_modules', OAK_CLI_MODULE_NAME, 'templateFiles', 'initialize.prod.ts'),
|
||||
join(cwd, 'node_modules', OAK_CLI_MODULE_NAME, 'templateFiles', 'initialize.frontend.ts'),
|
||||
join(cwd, 'node_modules', OAK_CLI_MODULE_NAME, 'templateFiles', 'initialize.server.ts'),
|
||||
join(cwd, 'node_modules', OAK_CLI_MODULE_NAME, 'templateFiles', 'initializeFeatures.ts'),
|
||||
join(cwd, 'node_modules', OAK_CLI_MODULE_NAME, 'templateFiles', 'RuntimeCxt.ts'),
|
||||
join(cwd, 'node_modules', OAK_CLI_MODULE_NAME, 'templateFiles', 'DependentExceptions.ts'),
|
||||
|
|
@ -1490,30 +1673,31 @@ export default function buildDependency(rebuild?: boolean) {
|
|||
const program = ts.createProgram(templateFileList, {});
|
||||
const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });
|
||||
|
||||
if (!isModule) {
|
||||
const initDevFile = join(cwd, 'src', 'initialize.frontend.ts');
|
||||
if (existsSync(initDevFile) && !rebuild) {
|
||||
console.log(`[${initDevFile}]文件已经存在,无需构建启动文件`);
|
||||
}
|
||||
else {
|
||||
outputIntializeDev(cwd, dependencies, briefNames, program.getSourceFile(templateFileList[0])!, printer, initDevFile);
|
||||
}
|
||||
|
||||
const initDevFile = join(cwd, 'src', 'initialize.dev.ts');
|
||||
if (existsSync(initDevFile) && !rebuild) {
|
||||
console.log(`[${initDevFile}]文件已经存在,无需构建启动文件`);
|
||||
}
|
||||
else {
|
||||
outputIntializeDev(cwd, dependencies, briefNames, program.getSourceFile(templateFileList[0])!, printer, initDevFile);
|
||||
}
|
||||
|
||||
const initProdFile = join(cwd, 'src', 'initialize.prod.ts');
|
||||
if (existsSync(initProdFile) && !rebuild) {
|
||||
console.log(`[${initProdFile}]文件已经存在,无需构建启动文件`);
|
||||
}
|
||||
else {
|
||||
outputIntializeProd(cwd, dependencies, briefNames, program.getSourceFile(templateFileList[1])!, printer, initProdFile);
|
||||
}
|
||||
const initProdFile = join(cwd, 'src', 'initialize.server.ts');
|
||||
if (existsSync(initProdFile) && !rebuild) {
|
||||
console.log(`[${initProdFile}]文件已经存在,无需构建启动文件`);
|
||||
}
|
||||
else {
|
||||
outputIntializeProd(cwd, dependencies, briefNames, program.getSourceFile(templateFileList[1])!, printer, initProdFile);
|
||||
}
|
||||
|
||||
|
||||
const initFeaturesFile = join(cwd, 'src', 'initializeFeatures.ts');
|
||||
if (existsSync(initFeaturesFile) && !rebuild) {
|
||||
console.log(`[${initFeaturesFile}]文件已经存在,无需构建启动文件`);
|
||||
}
|
||||
else {
|
||||
outputIntializeFeatures(cwd, dependencies, briefNames, program.getSourceFile(templateFileList[2])!, printer, initFeaturesFile);
|
||||
const initFeaturesFile = join(cwd, 'src', 'initializeFeatures.ts');
|
||||
if (existsSync(initFeaturesFile) && !rebuild) {
|
||||
console.log(`[${initFeaturesFile}]文件已经存在,无需构建启动文件`);
|
||||
}
|
||||
else {
|
||||
outputIntializeFeatures(cwd, dependencies, briefNames, program.getSourceFile(templateFileList[2])!, printer, initFeaturesFile);
|
||||
}
|
||||
}
|
||||
|
||||
const dependentContextFile = join(cwd, 'src', 'context', 'DependentContext.ts');
|
||||
|
|
@ -1553,9 +1737,11 @@ export default function buildDependency(rebuild?: boolean) {
|
|||
console.log(`[${featureIndexFile}]文件已经存在,无需构建启动文件`);
|
||||
}
|
||||
else {
|
||||
outputFeatureIndex(dependencies, briefNames, program.getSourceFile(templateFileList[6])!, printer, featureIndexFile);
|
||||
outputFeatureIndex(dependencies, briefNames, program.getSourceFile(templateFileList[6])!, printer, featureIndexFile, isModule);
|
||||
}
|
||||
|
||||
// 把各个依赖项目的一些初始化的文件拷贝过去
|
||||
tryCopyModuleTemplateFiles(cwd, dependencies, briefNames, printer);
|
||||
if (!isModule) {
|
||||
tryCopyModuleTemplateFiles(cwd, dependencies, briefNames, printer);
|
||||
}
|
||||
}
|
||||
|
|
@ -17,8 +17,8 @@ export abstract class AsyncContext<ED extends EntityDict> implements Context {
|
|||
opResult: OperationResult<ED>;
|
||||
private message?: string;
|
||||
events: {
|
||||
commit: Array<() => Promise<void>>;
|
||||
rollback: Array<() => Promise<void>>;
|
||||
commit: Array<(records: OpRecord<ED>[], cxtStr: string) => Promise<void>>;
|
||||
rollback: Array<(records: OpRecord<ED>[], cxtStr: string) => Promise<void>>;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -82,7 +82,7 @@ export abstract class AsyncContext<ED extends EntityDict> implements Context {
|
|||
};
|
||||
}
|
||||
|
||||
on(event: 'commit' | 'rollback', callback: () => Promise<void>): void {
|
||||
on(event: 'commit' | 'rollback', callback: (records: OpRecord<ED>[], cxtStr: string) => Promise<void>): void {
|
||||
this.uuid && this.events[event].push(callback);
|
||||
}
|
||||
|
||||
|
|
@ -136,9 +136,15 @@ export abstract class AsyncContext<ED extends EntityDict> implements Context {
|
|||
if (this.uuid) {
|
||||
await this.rowStore.commit(this.uuid!);
|
||||
const { commit: commitEvents } = this.events;
|
||||
for (const e of commitEvents) {
|
||||
/* for (const e of commitEvents) {
|
||||
await e();
|
||||
}
|
||||
} */
|
||||
|
||||
// 提交时不能等在跨事务trigger上
|
||||
const cxtStr = await this.toString();
|
||||
commitEvents.forEach(
|
||||
evt => evt(this.opRecords, cxtStr)
|
||||
);
|
||||
this.uuid = undefined;
|
||||
this.resetEvents();
|
||||
this.opRecords = [];
|
||||
|
|
@ -150,9 +156,12 @@ export abstract class AsyncContext<ED extends EntityDict> implements Context {
|
|||
if (this.uuid) {
|
||||
await this.rowStore.rollback(this.uuid!);
|
||||
const { rollback: rollbackEvents } = this.events;
|
||||
for (const e of rollbackEvents) {
|
||||
await e();
|
||||
}
|
||||
|
||||
// 回退时不能等在跨事务trigger上
|
||||
const cxtStr = await this.toString();
|
||||
rollbackEvents.forEach(
|
||||
evt => evt(this.opRecords, cxtStr)
|
||||
);
|
||||
this.uuid = undefined;
|
||||
this.opRecords = [];
|
||||
this.opResult = {};
|
||||
|
|
|
|||
|
|
@ -287,19 +287,22 @@ export class TriggerExecutor<ED extends EntityDict & BaseEntityDict, Cxt extends
|
|||
context: Cxt,
|
||||
option: OperateOption
|
||||
) {
|
||||
context.on('commit', async () => {
|
||||
context.on('commit', async (opRecords, cxtStr) => {
|
||||
let ids = [] as string[];
|
||||
let cxtStr = await context.toString();
|
||||
const { opRecords } = context;
|
||||
let cxtStr2 = cxtStr;
|
||||
const { data } = operation;
|
||||
if (operation.action === 'create') {
|
||||
if (data instanceof Array) {
|
||||
ids = data.map(ele => ele.id!);
|
||||
cxtStr = data[0].$$triggerData$$?.cxtStr || await context.toString();
|
||||
if (data[0].$$triggerData$$?.cxtStr) {
|
||||
cxtStr2 = data[0].$$triggerData$$?.cxtStr;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ids = [data.id!];
|
||||
cxtStr = data.$$triggerData$$?.cxtStr || await context.toString();
|
||||
if (data.$$triggerData$$?.cxtStr) {
|
||||
cxtStr2 = data.$$triggerData$$?.cxtStr;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
@ -308,7 +311,9 @@ export class TriggerExecutor<ED extends EntityDict & BaseEntityDict, Cxt extends
|
|||
* 若trigger是takeEasy,只会在事务提交时做一次,使用当前context应也无大问题
|
||||
* 暂时先这样设计,若当前提交事务中改变了cxt内容,也许会有问题。by Xc 20240319
|
||||
*/
|
||||
cxtStr = (<ED[T]['Update']['data']>data).$$triggerData$$?.cxtStr || await context.toString();
|
||||
if ((<ED[T]['Update']['data']>data).$$triggerData$$?.cxtStr) {
|
||||
cxtStr2 = (<ED[T]['Update']['data']>data).$$triggerData$$?.cxtStr;
|
||||
}
|
||||
const record = opRecords.find(
|
||||
ele => (ele as CreateOpResult<ED, keyof ED>).id === operation.id,
|
||||
);
|
||||
|
|
@ -318,7 +323,7 @@ export class TriggerExecutor<ED extends EntityDict & BaseEntityDict, Cxt extends
|
|||
ids = f!.id!.$in;
|
||||
}
|
||||
// 此时项目的上下文,和执行此trigger时的上下文可能不一致(rootMode),采用当时的上下文cxtStr来执行
|
||||
this.onVolatileTrigger(entity, trigger, ids, cxtStr, option);
|
||||
this.onVolatileTrigger(entity, trigger, ids, cxtStr2, option);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -426,6 +431,8 @@ export class TriggerExecutor<ED extends EntityDict & BaseEntityDict, Cxt extends
|
|||
const { fn } = trigger as VolatileTrigger<ED, T, Cxt>;
|
||||
const callback = await fn({ ids }, context, option);
|
||||
if (trigger.strict === 'makeSure') {
|
||||
// 这里开root模式,否则还可能有权限问题
|
||||
context.openRootMode();
|
||||
await context.operate(entity, {
|
||||
id: await generateNewIdAsync(),
|
||||
action: 'update',
|
||||
|
|
|
|||
|
|
@ -1,17 +1,14 @@
|
|||
// 将项目的所有配置规范化到一起(未完成)by Xc 20240207
|
||||
import { AuthDeduceRelationMap, EntityDict } from './Entity';
|
||||
import { EntityDict as BaseEntityDict } from "../base-app-domain";
|
||||
import { AsyncContext } from '../store/AsyncRowStore';
|
||||
import { SyncConfig } from "./Sync";
|
||||
import { AttrUpdateMatrix } from './EntityDesc';
|
||||
import { ActionDefDict } from './Action';
|
||||
import { StyleDict } from './Style';
|
||||
import { Exportation, Importation } from './Port';
|
||||
|
||||
/**
|
||||
* 后台配置
|
||||
*/
|
||||
export type ServerConfiguration<ED extends BaseEntityDict & EntityDict, Cxt extends AsyncContext<ED>> = {
|
||||
export type ServerConfiguration = {
|
||||
database: {
|
||||
type: 'mysql',
|
||||
host: string;
|
||||
|
|
@ -25,7 +22,20 @@ export type ServerConfiguration<ED extends BaseEntityDict & EntityDict, Cxt exte
|
|||
workDir: {
|
||||
path: string;
|
||||
},
|
||||
sync?: SyncConfig<ED, Cxt>;
|
||||
port: number;
|
||||
hostname: string;
|
||||
nginx?: {
|
||||
ssl: boolean;
|
||||
apiPath: string;
|
||||
port?: number;
|
||||
socketPath: string;
|
||||
},
|
||||
cors?: {
|
||||
origin: string;
|
||||
headers?: string[];
|
||||
methods?: string[];
|
||||
},
|
||||
internalExceptionMask?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -392,71 +392,71 @@ export function makeException<ED extends EntityDict>(data: {
|
|||
break;
|
||||
}
|
||||
case 'OakUserException': {
|
||||
const e = new OakUserException(data.message);
|
||||
e = new OakUserException(data.message);
|
||||
break;
|
||||
}
|
||||
case 'OakRowInconsistencyException': {
|
||||
const e = new OakRowInconsistencyException(data.data, data.message);
|
||||
e = new OakRowInconsistencyException(data.data, data.message);
|
||||
break;
|
||||
}
|
||||
case 'OakInputIllegalException': {
|
||||
const e = new OakInputIllegalException(data.entity, data.attributes, data.message);
|
||||
e = new OakInputIllegalException(data.entity, data.attributes, data.message);
|
||||
break;
|
||||
}
|
||||
case 'OakAttrCantUpdateException': {
|
||||
const e = new OakAttrCantUpdateException(data.entity, data.attributes, data.message);
|
||||
e = new OakAttrCantUpdateException(data.entity, data.attributes, data.message);
|
||||
break;
|
||||
}
|
||||
case 'OakUserUnpermittedException': {
|
||||
const e = new OakUserUnpermittedException(data.entity, data.operation, data.message);
|
||||
e = new OakUserUnpermittedException(data.entity, data.operation, data.message);
|
||||
break;
|
||||
}
|
||||
case 'OakUserInvisibleException': {
|
||||
const e = new OakUserInvisibleException(data.entity, data.operation, data.message);
|
||||
e = new OakUserInvisibleException(data.entity, data.operation, data.message);
|
||||
break;
|
||||
}
|
||||
case 'OakUnloggedInException': {
|
||||
const e = new OakUnloggedInException(data.message);
|
||||
e = new OakUnloggedInException(data.message);
|
||||
break;
|
||||
}
|
||||
case 'OakCongruentRowExists': {
|
||||
const e = new OakCongruentRowExists(data.entity, data.data, data.message);
|
||||
e = new OakCongruentRowExists(data.entity, data.data, data.message);
|
||||
break;
|
||||
}
|
||||
case 'OakRowLockedException': {
|
||||
const e = new OakRowLockedException(data.message);
|
||||
e = new OakRowLockedException(data.message);
|
||||
break;
|
||||
}
|
||||
case 'OakRowUnexistedException': {
|
||||
const e = new OakRowUnexistedException(data.rows);
|
||||
e = new OakRowUnexistedException(data.rows);
|
||||
break;
|
||||
}
|
||||
case 'OakDeadlock': {
|
||||
const e = new OakDeadlock(data.message);
|
||||
e = new OakDeadlock(data.message);
|
||||
break;
|
||||
}
|
||||
case 'OakDataException': {
|
||||
const e = new OakDataException(data.message);
|
||||
e = new OakDataException(data.message);
|
||||
break;
|
||||
}
|
||||
case 'OakNoRelationDefException': {
|
||||
const e = new OakNoRelationDefException(data.entity, data.action, data.message);
|
||||
e = new OakNoRelationDefException(data.entity, data.action, data.message);
|
||||
break;
|
||||
}
|
||||
case 'OakUniqueViolationException': {
|
||||
const e = new OakUniqueViolationException(data.rows, data.message);
|
||||
e = new OakUniqueViolationException(data.rows, data.message);
|
||||
break;
|
||||
}
|
||||
case 'OakImportDataParseException': {
|
||||
const e = new OakImportDataParseException(data.message!, data.line, data.header);
|
||||
e = new OakImportDataParseException(data.message!, data.line, data.header);
|
||||
break;
|
||||
}
|
||||
case 'OakPreConditionUnsetException': {
|
||||
const e = new OakPreConditionUnsetException(data.message, data.entity, data.code);
|
||||
e = new OakPreConditionUnsetException(data.message, data.entity, data.code);
|
||||
break;
|
||||
}
|
||||
case 'OakAttrNotNullException': {
|
||||
const e = new OakAttrNotNullException(
|
||||
e = new OakAttrNotNullException(
|
||||
data.entity,
|
||||
data.attributes,
|
||||
data.message
|
||||
|
|
@ -464,15 +464,15 @@ export function makeException<ED extends EntityDict>(data: {
|
|||
break;
|
||||
}
|
||||
case 'OakExternalException': {
|
||||
const e = new OakExternalException(data.source, data.code, data.message, data.data);
|
||||
e = new OakExternalException(data.source, data.code, data.message, data.data);
|
||||
break;
|
||||
}
|
||||
case 'OakNetworkException': {
|
||||
const e = new OakNetworkException(data.message);
|
||||
e = new OakNetworkException(data.message);
|
||||
break;
|
||||
}
|
||||
case 'OakServerProxyException': {
|
||||
const e = new OakServerProxyException(data.message);
|
||||
e = new OakServerProxyException(data.message);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -161,18 +161,10 @@ export default class SimpleConnector<ED extends EntityDict, FrontCxt extends Syn
|
|||
response.headers.get('Content-Type') ||
|
||||
response.headers.get('content-type');
|
||||
if (responseType?.toLocaleLowerCase().match(/application\/json/i)) {
|
||||
const { url, path, port, namespace } = await response.json();
|
||||
|
||||
let url2 = url || this.serverUrl;
|
||||
if (port) {
|
||||
url2 += `:${port}`;
|
||||
}
|
||||
if (namespace) {
|
||||
url2 += namespace;
|
||||
}
|
||||
const { url, path } = await response.json();
|
||||
|
||||
return {
|
||||
url: url2,
|
||||
url,
|
||||
path,
|
||||
};
|
||||
} else {
|
||||
|
|
|
|||
Loading…
Reference in New Issue