修改了框架的大量语法
This commit is contained in:
parent
ba073f572d
commit
8198b81479
|
|
@ -42,6 +42,7 @@ const ActionImportStatements = () => [
|
|||
factory.createImportDeclaration(undefined, undefined, factory.createImportClause(false, undefined, factory.createNamedImports([factory.createImportSpecifier(false, undefined, factory.createIdentifier("GenericAction"))])), factory.createStringLiteral((0, env_1.ACTION_CONSTANT_IN_OAK_DOMAIN)()), undefined)
|
||||
];
|
||||
const ActionAsts = {};
|
||||
const SchemaAsts = {};
|
||||
function addRelationship(many, one, key) {
|
||||
const { [many]: manySet } = ManyToOne;
|
||||
const one2 = one === 'Schema' ? many : one;
|
||||
|
|
@ -83,6 +84,19 @@ function pushStatementIntoActionAst(moduleName, node, sourceFile) {
|
|||
});
|
||||
}
|
||||
}
|
||||
function pushStatementIntoSchemaAst(moduleName, statement, sourceFile) {
|
||||
if (SchemaAsts[moduleName]) {
|
||||
SchemaAsts[moduleName].statements.push(statement);
|
||||
}
|
||||
else {
|
||||
(0, lodash_1.assign)(SchemaAsts, {
|
||||
[moduleName]: {
|
||||
statements: [statement],
|
||||
sourceFile,
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 检查ActionDef是否满足合法的定义
|
||||
* 1、ActionDef, Action, State三者命名是否一致
|
||||
|
|
@ -220,6 +234,7 @@ function analyzeEntity(filename, path, program) {
|
|||
const schemaAttrs = [];
|
||||
let hasFulltextIndex = false;
|
||||
let indexes;
|
||||
let beforeSchema = true;
|
||||
ts.forEachChild(sourceFile, (node) => {
|
||||
if (ts.isImportDeclaration(node)) {
|
||||
const entityImported = getEntityImported(node, filename);
|
||||
|
|
@ -309,6 +324,11 @@ function analyzeEntity(filename, path, program) {
|
|||
[moduleName]: 1,
|
||||
});
|
||||
}
|
||||
beforeSchema = false;
|
||||
}
|
||||
else if (beforeSchema) {
|
||||
// 本地规定的一些形状定义,直接使用
|
||||
pushStatementIntoSchemaAst(moduleName, node, sourceFile);
|
||||
}
|
||||
}
|
||||
if (ts.isTypeAliasDeclaration(node)) {
|
||||
|
|
@ -322,7 +342,7 @@ function analyzeEntity(filename, path, program) {
|
|||
])), sourceFile);
|
||||
dealWithActions(moduleName, filename, node.type, program, schemaAttrs);
|
||||
}
|
||||
if (node.name.text === 'Relation') {
|
||||
else if (node.name.text === 'Relation') {
|
||||
// 增加userXXX对象的描述
|
||||
if (ts.isLiteralTypeNode(node.type)) {
|
||||
(0, assert_1.default)(ts.isStringLiteral(node.type.literal));
|
||||
|
|
@ -351,6 +371,10 @@ function analyzeEntity(filename, path, program) {
|
|||
addRelationship(relationEntityName, 'User', 'user');
|
||||
addRelationship(relationEntityName, moduleName, entityLc);
|
||||
}
|
||||
else if (beforeSchema) {
|
||||
// 本地规定的一些形状定义,直接使用
|
||||
pushStatementIntoSchemaAst(moduleName, node, sourceFile);
|
||||
}
|
||||
}
|
||||
if (ts.isVariableStatement(node)) {
|
||||
const { declarationList: { declarations } } = node;
|
||||
|
|
@ -633,6 +657,10 @@ function constructSchema(statements, entity) {
|
|||
statements.push(factory.createImportDeclaration(undefined, undefined, factory.createImportClause(false, undefined, factory.createNamespaceImport(factory.createIdentifier(ele))), factory.createStringLiteral(`../${ele}/Schema`)));
|
||||
}
|
||||
});
|
||||
// 在这里把需要直接拷贝过来的语句写入
|
||||
if (SchemaAsts[entity]) {
|
||||
statements.push(...SchemaAsts[entity].statements);
|
||||
}
|
||||
// if (keys(foreignKeySet).length > 0) {
|
||||
// for (const fkItem in foreignKeySet) {
|
||||
// const entityLc = fkItem.slice(0, 1).toLowerCase().concat(fkItem.slice(1));
|
||||
|
|
@ -770,12 +798,14 @@ function constructFilter(statements, entity) {
|
|||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
(0, assert_1.default)(ts.isUnionTypeNode(type) && ts.isLiteralTypeNode(type.types[0]) || ts.isLiteralTypeNode(type));
|
||||
else if (ts.isUnionTypeNode(type) && ts.isLiteralTypeNode(type.types[0]) || ts.isLiteralTypeNode(type)) {
|
||||
members.push(factory.createPropertySignature(undefined, name, undefined, factory.createTypeReferenceNode(factory.createIdentifier('Q_EnumValue'), [
|
||||
type
|
||||
])));
|
||||
}
|
||||
else {
|
||||
// 此时应当是引用本地定义的shape
|
||||
}
|
||||
}
|
||||
// type AttrFilter = {};
|
||||
const eumUnionTypeNode = ReversePointerRelations[entity] && ReversePointerRelations[entity].map(ele => factory.createLiteralTypeNode(factory.createStringLiteral((0, utils_1.firstLetterLowerCase)(ele))));
|
||||
|
|
@ -876,7 +906,8 @@ function constructProjection(statements, entity) {
|
|||
}
|
||||
}
|
||||
else {
|
||||
(0, assert_1.default)(ts.isUnionTypeNode(type) && ts.isLiteralTypeNode(type.types[0]) || ts.isLiteralTypeNode(type));
|
||||
// 增加了本身object的shape定义
|
||||
// assert(ts.isUnionTypeNode(type!) && ts.isLiteralTypeNode(type.types[0]) || ts.isLiteralTypeNode(type!));
|
||||
properties.push([name, false, undefined]);
|
||||
}
|
||||
}
|
||||
|
|
@ -1128,10 +1159,12 @@ function constructSorter(statements, entity) {
|
|||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
(0, assert_1.default)(ts.isUnionTypeNode(type) && ts.isLiteralTypeNode(type.types[0]) || ts.isLiteralTypeNode(type));
|
||||
else if (ts.isUnionTypeNode(type) && ts.isLiteralTypeNode(type.types[0]) || ts.isLiteralTypeNode(type)) {
|
||||
members.push(factory.createPropertySignature(undefined, name, undefined, factory.createLiteralTypeNode(factory.createNumericLiteral("1"))));
|
||||
}
|
||||
else {
|
||||
// 本地规定的shape,非结构化属性不参与排序
|
||||
}
|
||||
}
|
||||
if (ReversePointerRelations[entity]) {
|
||||
ReversePointerRelations[entity].forEach((one) => {
|
||||
|
|
@ -1862,29 +1895,39 @@ function constructAttributes(entity) {
|
|||
}
|
||||
else {
|
||||
if (ts.isUnionTypeNode(type)) {
|
||||
(0, assert_1.default)(ts.isLiteralTypeNode(type.types[0]));
|
||||
if (ts.isStringLiteral(type.types[0].literal)) {
|
||||
attrAssignments.push(factory.createPropertyAssignment(factory.createIdentifier("type"), factory.createStringLiteral("varchar")), factory.createPropertyAssignment(factory.createIdentifier("params"), factory.createObjectLiteralExpression([factory.createPropertyAssignment(factory.createIdentifier("length"), factory.createNumericLiteral(env_1.STRING_LITERAL_MAX_LENGTH))], true)));
|
||||
if (ts.isLiteralTypeNode(type.types[0])) {
|
||||
if (ts.isStringLiteral(type.types[0].literal)) {
|
||||
attrAssignments.push(factory.createPropertyAssignment(factory.createIdentifier("type"), factory.createStringLiteral("varchar")), factory.createPropertyAssignment(factory.createIdentifier("params"), factory.createObjectLiteralExpression([factory.createPropertyAssignment(factory.createIdentifier("length"), factory.createNumericLiteral(env_1.STRING_LITERAL_MAX_LENGTH))], true)));
|
||||
}
|
||||
else {
|
||||
(0, assert_1.default)(ts.isNumericLiteral(type.types[0].literal));
|
||||
attrAssignments.push(factory.createPropertyAssignment(factory.createIdentifier("type"), factory.createStringLiteral("int")), factory.createPropertyAssignment(factory.createIdentifier("params"), factory.createObjectLiteralExpression([
|
||||
factory.createPropertyAssignment(factory.createIdentifier("precision"), factory.createNumericLiteral(env_1.NUMERICAL_LITERL_DEFAULT_PRECISION)),
|
||||
factory.createPropertyAssignment(factory.createIdentifier("scale"), factory.createNumericLiteral(env_1.NUMERICAL_LITERL_DEFAULT_SCALE))
|
||||
], true)));
|
||||
}
|
||||
}
|
||||
else {
|
||||
(0, assert_1.default)(ts.isNumericLiteral(type.types[0].literal));
|
||||
attrAssignments.push(factory.createPropertyAssignment(factory.createIdentifier("type"), factory.createStringLiteral("int")), factory.createPropertyAssignment(factory.createIdentifier("params"), factory.createObjectLiteralExpression([
|
||||
factory.createPropertyAssignment(factory.createIdentifier("precision"), factory.createNumericLiteral(env_1.NUMERICAL_LITERL_DEFAULT_PRECISION)),
|
||||
factory.createPropertyAssignment(factory.createIdentifier("scale"), factory.createNumericLiteral(env_1.NUMERICAL_LITERL_DEFAULT_SCALE))
|
||||
], true)));
|
||||
// 否则是本地规定的shape,直接用object
|
||||
attrAssignments.push(factory.createPropertyAssignment(factory.createIdentifier("type"), factory.createStringLiteral("object")));
|
||||
}
|
||||
}
|
||||
else {
|
||||
(0, assert_1.default)(ts.isLiteralTypeNode(type), `${entity}中的属性${name.text}有非法的属性类型定义`);
|
||||
if (ts.isStringLiteral(type.literal)) {
|
||||
attrAssignments.push(factory.createPropertyAssignment(factory.createIdentifier("type"), factory.createStringLiteral("varchar")), factory.createPropertyAssignment(factory.createIdentifier("params"), factory.createObjectLiteralExpression([factory.createPropertyAssignment(factory.createIdentifier("length"), factory.createNumericLiteral(env_1.STRING_LITERAL_MAX_LENGTH))], true)));
|
||||
if (ts.isLiteralTypeNode(type)) {
|
||||
if (ts.isStringLiteral(type.literal)) {
|
||||
attrAssignments.push(factory.createPropertyAssignment(factory.createIdentifier("type"), factory.createStringLiteral("varchar")), factory.createPropertyAssignment(factory.createIdentifier("params"), factory.createObjectLiteralExpression([factory.createPropertyAssignment(factory.createIdentifier("length"), factory.createNumericLiteral(env_1.STRING_LITERAL_MAX_LENGTH))], true)));
|
||||
}
|
||||
else {
|
||||
(0, assert_1.default)(ts.isNumericLiteral(type.literal));
|
||||
attrAssignments.push(factory.createPropertyAssignment(factory.createIdentifier("type"), factory.createStringLiteral("precision")), factory.createPropertyAssignment(factory.createIdentifier("params"), factory.createObjectLiteralExpression([
|
||||
factory.createPropertyAssignment(factory.createIdentifier("precision"), factory.createNumericLiteral(env_1.NUMERICAL_LITERL_DEFAULT_PRECISION)),
|
||||
factory.createPropertyAssignment(factory.createIdentifier("scale"), factory.createNumericLiteral(env_1.NUMERICAL_LITERL_DEFAULT_SCALE))
|
||||
], true)));
|
||||
}
|
||||
}
|
||||
else {
|
||||
(0, assert_1.default)(ts.isNumericLiteral(type.literal));
|
||||
attrAssignments.push(factory.createPropertyAssignment(factory.createIdentifier("type"), factory.createStringLiteral("precision")), factory.createPropertyAssignment(factory.createIdentifier("params"), factory.createObjectLiteralExpression([
|
||||
factory.createPropertyAssignment(factory.createIdentifier("precision"), factory.createNumericLiteral(env_1.NUMERICAL_LITERL_DEFAULT_PRECISION)),
|
||||
factory.createPropertyAssignment(factory.createIdentifier("scale"), factory.createNumericLiteral(env_1.NUMERICAL_LITERL_DEFAULT_SCALE))
|
||||
], true)));
|
||||
// 否则是本地规定的shape,直接用object
|
||||
attrAssignments.push(factory.createPropertyAssignment(factory.createIdentifier("type"), factory.createStringLiteral("object")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,13 @@
|
|||
import { Context } from '../types/Context';
|
||||
import { DeduceCreateOperation, DeduceCreateSingleOperation, DeduceRemoveOperation, DeduceUpdateOperation, EntityDef, OperateParams } from "../types/Entity";
|
||||
import { DeduceCreateOperation, DeduceCreateSingleOperation, DeduceRemoveOperation, DeduceUpdateOperation, EntityDict, OperateParams } from "../types/Entity";
|
||||
import { RowStore } from '../types/RowStore';
|
||||
import { StorageSchema } from '../types/Storage';
|
||||
/**这个用来处理级联的select和update,对不同能力的 */
|
||||
export declare abstract class CascadeStore<ED extends {
|
||||
[E: string]: EntityDef;
|
||||
}> extends RowStore<ED> {
|
||||
export declare abstract class CascadeStore<ED extends EntityDict, Cxt extends Context<ED>> extends RowStore<ED, Cxt> {
|
||||
constructor(storageSchema: StorageSchema<ED>);
|
||||
protected abstract selectAbjointRow<T extends keyof ED>(entity: T, selection: Omit<ED[T]['Selection'], 'indexFrom' | 'count' | 'data' | 'sorter'>, context: Context<ED>, params?: OperateParams): Promise<Array<ED[T]['OpSchema']>>;
|
||||
protected abstract updateAbjointRow<T extends keyof ED>(entity: T, operation: DeduceCreateSingleOperation<ED[T]['Schema']> | DeduceUpdateOperation<ED[T]['Schema']> | DeduceRemoveOperation<ED[T]['Schema']>, context: Context<ED>, params?: OperateParams): Promise<void>;
|
||||
protected cascadeSelect<T extends keyof ED>(entity: T, selection: ED[T]['Selection'], context: Context<ED>, params?: OperateParams): Promise<Array<ED[T]['Schema']>>;
|
||||
protected abstract selectAbjointRow<T extends keyof ED>(entity: T, selection: Omit<ED[T]['Selection'], 'indexFrom' | 'count' | 'data' | 'sorter'>, context: Cxt, params?: OperateParams): Promise<Array<ED[T]['OpSchema']>>;
|
||||
protected abstract updateAbjointRow<T extends keyof ED>(entity: T, operation: DeduceCreateSingleOperation<ED[T]['Schema']> | DeduceUpdateOperation<ED[T]['Schema']> | DeduceRemoveOperation<ED[T]['Schema']>, context: Cxt, params?: OperateParams): Promise<void>;
|
||||
protected cascadeSelect<T extends keyof ED>(entity: T, selection: ED[T]['Selection'], context: Cxt, params?: OperateParams): Promise<Array<ED[T]['Schema']>>;
|
||||
/**
|
||||
* 级联更新
|
||||
* A --> B
|
||||
|
|
@ -33,6 +31,6 @@ export declare abstract class CascadeStore<ED extends {
|
|||
* @param context
|
||||
* @param params
|
||||
*/
|
||||
protected cascadeUpdate<T extends keyof ED>(entity: T, operation: DeduceCreateOperation<ED[T]['Schema']> | DeduceUpdateOperation<ED[T]['Schema']> | DeduceRemoveOperation<ED[T]['Schema']>, context: Context<ED>, params?: OperateParams): Promise<void>;
|
||||
protected cascadeUpdate<T extends keyof ED>(entity: T, operation: DeduceCreateOperation<ED[T]['Schema']> | DeduceUpdateOperation<ED[T]['Schema']> | DeduceRemoveOperation<ED[T]['Schema']>, context: Cxt, params?: OperateParams): Promise<void>;
|
||||
judgeRelation(entity: keyof ED, attr: string): string | string[] | 1 | 0 | 2;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,19 +6,20 @@ import { Trigger, Executor } from "../types/Trigger";
|
|||
/**
|
||||
* update可能会传入多种不同的action,此时都需要检查update trigger
|
||||
*/
|
||||
export declare class TriggerExecutor<ED extends EntityDict> extends Executor<ED> {
|
||||
export declare class TriggerExecutor<ED extends EntityDict, Cxt extends Context<ED>> extends Executor<ED, Cxt> {
|
||||
private triggerMap;
|
||||
private triggerNameMap;
|
||||
private volatileEntities;
|
||||
private logger;
|
||||
constructor(logger?: Logger);
|
||||
registerChecker<T extends keyof ED>(checker: Checker<ED, T>): void;
|
||||
registerTrigger<T extends keyof ED>(trigger: Trigger<ED, T>): void;
|
||||
unregisterTrigger<T extends keyof ED>(trigger: Trigger<ED, T>): void;
|
||||
private contextBuilder;
|
||||
constructor(contextBuilder: () => Cxt, logger?: Logger);
|
||||
registerChecker<T extends keyof ED>(checker: Checker<ED, T, Cxt>): void;
|
||||
registerTrigger<T extends keyof ED>(trigger: Trigger<ED, T, Cxt>): void;
|
||||
unregisterTrigger<T extends keyof ED>(trigger: Trigger<ED, T, Cxt>): void;
|
||||
private preCommitTrigger;
|
||||
preOperation<T extends keyof ED>(entity: T, operation: ED[T]['Operation'], context: Context<ED>): Promise<void>;
|
||||
preOperation<T extends keyof ED>(entity: T, operation: ED[T]['Operation'], context: Cxt): Promise<void>;
|
||||
private onCommit;
|
||||
private postCommitTrigger;
|
||||
postOperation<T extends keyof ED>(entity: T, operation: ED[T]['Operation'], context: Context<ED>): Promise<void>;
|
||||
checkpoint(context: Context<ED>, timestamp: number): Promise<number>;
|
||||
postOperation<T extends keyof ED>(entity: T, operation: ED[T]['Operation'], context: Cxt): Promise<void>;
|
||||
checkpoint(context: Cxt, timestamp: number): Promise<number>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,8 +24,10 @@ class TriggerExecutor extends Trigger_1.Executor {
|
|||
triggerNameMap;
|
||||
volatileEntities;
|
||||
logger;
|
||||
constructor(logger = console) {
|
||||
contextBuilder;
|
||||
constructor(contextBuilder, logger = console) {
|
||||
super();
|
||||
this.contextBuilder = contextBuilder;
|
||||
this.logger = logger;
|
||||
this.triggerMap = {};
|
||||
this.triggerNameMap = {};
|
||||
|
|
@ -166,7 +168,8 @@ class TriggerExecutor extends Trigger_1.Executor {
|
|||
}
|
||||
}
|
||||
onCommit(trigger, operation) {
|
||||
return async (context) => {
|
||||
return async () => {
|
||||
const context = this.contextBuilder();
|
||||
await context.begin();
|
||||
const number = await trigger.fn({
|
||||
operation: operation,
|
||||
|
|
@ -243,7 +246,7 @@ class TriggerExecutor extends Trigger_1.Executor {
|
|||
const { $$triggerData$$ } = row;
|
||||
const { name, operation } = $$triggerData$$;
|
||||
const trigger = this.triggerNameMap[name];
|
||||
await this.onCommit(trigger, operation)(context);
|
||||
await this.onCommit(trigger, operation)();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
import { EntityDict, OpRecord, RowStore, TxnOption, Context } from "../types";
|
||||
export declare class UniversalContext<ED extends EntityDict> implements Context<ED> {
|
||||
rowStore: RowStore<ED>;
|
||||
rowStore: RowStore<ED, this>;
|
||||
uuid?: string;
|
||||
opRecords: OpRecord<ED>[];
|
||||
events: {
|
||||
commit: Array<(context: UniversalContext<ED>) => Promise<void>>;
|
||||
rollback: Array<(context: UniversalContext<ED>) => Promise<void>>;
|
||||
commit: Array<() => Promise<void>>;
|
||||
rollback: Array<() => Promise<void>>;
|
||||
};
|
||||
constructor(store: RowStore<ED>);
|
||||
constructor(store: RowStore<ED, UniversalContext<ED>>);
|
||||
private resetEvents;
|
||||
on(event: 'commit' | 'rollback', callback: (context: UniversalContext<ED>) => Promise<void>): void;
|
||||
on(event: 'commit' | 'rollback', callback: () => Promise<void>): void;
|
||||
begin(options?: TxnOption): Promise<void>;
|
||||
commit(): Promise<void>;
|
||||
rollback(): Promise<void>;
|
||||
|
|
|
|||
|
|
@ -30,27 +30,21 @@ class UniversalContext {
|
|||
}
|
||||
async commit() {
|
||||
if (this.uuid) {
|
||||
/**
|
||||
* todo 这里应该等到提交成功了再做 by Xc
|
||||
*/
|
||||
for (const e of this.events.commit) {
|
||||
await e(this);
|
||||
}
|
||||
await this.rowStore.commit(this.uuid);
|
||||
this.uuid = undefined;
|
||||
for (const e of this.events.commit) {
|
||||
await e();
|
||||
}
|
||||
this.resetEvents();
|
||||
}
|
||||
}
|
||||
async rollback() {
|
||||
if (this.uuid) {
|
||||
/**
|
||||
* todo 这里应该等到回滚成功了再做 by Xc
|
||||
*/
|
||||
for (const e of this.events.rollback) {
|
||||
await e(this);
|
||||
}
|
||||
await this.rowStore.rollback(this.uuid);
|
||||
this.uuid = undefined;
|
||||
for (const e of this.events.rollback) {
|
||||
await e();
|
||||
}
|
||||
this.resetEvents();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,23 +1,19 @@
|
|||
import { EntityDict } from "../types/Entity";
|
||||
import { Context } from "./Context";
|
||||
import { CreateTriggerBase, RemoveTriggerBase, UpdateTriggerBase } from "./Trigger";
|
||||
export declare class AttrIllegalError extends Error {
|
||||
private attributes;
|
||||
constructor(attributes: string[], message?: string);
|
||||
getAttributes(): string[];
|
||||
}
|
||||
export declare type CreateChecker<ED extends EntityDict, T extends keyof ED> = {
|
||||
export declare type CreateChecker<ED extends EntityDict, T extends keyof ED, Cxt extends Context<ED>> = {
|
||||
action: 'create';
|
||||
entity: T;
|
||||
checker: CreateTriggerBase<ED, T>['fn'];
|
||||
checker: CreateTriggerBase<ED, T, Cxt>['fn'];
|
||||
};
|
||||
export declare type UpdateChecker<ED extends EntityDict, T extends keyof ED> = {
|
||||
action: UpdateTriggerBase<ED, T>['action'];
|
||||
export declare type UpdateChecker<ED extends EntityDict, T extends keyof ED, Cxt extends Context<ED>> = {
|
||||
action: UpdateTriggerBase<ED, T, Cxt>['action'];
|
||||
entity: T;
|
||||
checker: UpdateTriggerBase<ED, T>['fn'];
|
||||
checker: UpdateTriggerBase<ED, T, Cxt>['fn'];
|
||||
};
|
||||
export declare type RemoveChecker<ED extends EntityDict, T extends keyof ED> = {
|
||||
export declare type RemoveChecker<ED extends EntityDict, T extends keyof ED, Cxt extends Context<ED>> = {
|
||||
action: 'remove';
|
||||
entity: T;
|
||||
checker: RemoveTriggerBase<ED, T>['fn'];
|
||||
checker: RemoveTriggerBase<ED, T, Cxt>['fn'];
|
||||
};
|
||||
export declare type Checker<ED extends EntityDict, T extends keyof ED> = CreateChecker<ED, T> | UpdateChecker<ED, T> | RemoveChecker<ED, T>;
|
||||
export declare type Checker<ED extends EntityDict, T extends keyof ED, Cxt extends Context<ED>> = CreateChecker<ED, T, Cxt> | UpdateChecker<ED, T, Cxt> | RemoveChecker<ED, T, Cxt>;
|
||||
|
|
|
|||
|
|
@ -1,15 +1,2 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.AttrIllegalError = void 0;
|
||||
class AttrIllegalError extends Error {
|
||||
attributes;
|
||||
constructor(attributes, message) {
|
||||
super(message);
|
||||
this.attributes = attributes;
|
||||
}
|
||||
getAttributes() {
|
||||
return this.attributes;
|
||||
}
|
||||
}
|
||||
exports.AttrIllegalError = AttrIllegalError;
|
||||
;
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@ import { EntityDict, OpRecord } from './Entity';
|
|||
import { RowStore } from './RowStore';
|
||||
export interface Context<ED extends EntityDict> {
|
||||
opRecords: OpRecord<ED>[];
|
||||
rowStore: RowStore<ED>;
|
||||
rowStore: RowStore<ED, this>;
|
||||
begin(options?: object): Promise<void>;
|
||||
commit(): Promise<void>;
|
||||
rollback(): Promise<void>;
|
||||
getCurrentTxnId(): string | undefined;
|
||||
on(event: 'commit' | 'rollback', callback: (context: Context<ED>) => Promise<void>): void;
|
||||
on(event: 'commit' | 'rollback', callback: () => Promise<void>): void;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,13 +5,13 @@ import { OakErrorDefDict } from '../OakError';
|
|||
export declare type TxnOption = {
|
||||
isolationLevel: 'repeatable read' | 'serializable';
|
||||
};
|
||||
export declare abstract class RowStore<ED extends EntityDict> {
|
||||
export declare abstract class RowStore<ED extends EntityDict, Cxt extends Context<ED>> {
|
||||
static $$LEVEL: string;
|
||||
static $$CODES: OakErrorDefDict;
|
||||
protected storageSchema: StorageSchema<ED>;
|
||||
abstract operate<T extends keyof ED>(entity: T, operation: ED[T]['Operation'], context: Context<ED>, params?: OperateParams): Promise<OperationResult>;
|
||||
abstract select<T extends keyof ED, S extends ED[T]['Selection']>(entity: T, selection: S, context: Context<ED>, params?: Object): Promise<SelectionResult<ED[T]['Schema'], S['data']>>;
|
||||
abstract count<T extends keyof ED>(entity: T, selection: Omit<ED[T]['Selection'], 'data' | 'sorter' | 'action'>, context: Context<ED>, params?: Object): Promise<number>;
|
||||
abstract operate<T extends keyof ED>(entity: T, operation: ED[T]['Operation'], context: Cxt, params?: OperateParams): Promise<OperationResult>;
|
||||
abstract select<T extends keyof ED, S extends ED[T]['Selection']>(entity: T, selection: S, context: Cxt, params?: Object): Promise<SelectionResult<ED[T]['Schema'], S['data']>>;
|
||||
abstract count<T extends keyof ED>(entity: T, selection: Omit<ED[T]['Selection'], 'data' | 'sorter' | 'action'>, context: Cxt, params?: Object): Promise<number>;
|
||||
constructor(storageSchema: StorageSchema<ED>);
|
||||
abstract begin(option?: TxnOption): Promise<string>;
|
||||
abstract commit(txnId: string): Promise<void>;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { GenericAction } from "../actions/action";
|
|||
import { DeduceCreateOperation, DeduceRemoveOperation, DeduceSelection, DeduceUpdateOperation, EntityDict } from "../types/Entity";
|
||||
import { EntityShape, SelectionResult, TriggerDataAttribute, TriggerTimestampAttribute } from "../types/Entity";
|
||||
import { Context } from "./Context";
|
||||
export interface CreateTriggerBase<ED extends EntityDict, T extends keyof ED> {
|
||||
export interface CreateTriggerBase<ED extends EntityDict, T extends keyof ED, Cxt extends Context<ED>> {
|
||||
entity: T;
|
||||
name: string;
|
||||
action: 'create';
|
||||
|
|
@ -11,15 +11,15 @@ export interface CreateTriggerBase<ED extends EntityDict, T extends keyof ED> {
|
|||
operation: DeduceCreateOperation<ED[T]['Schema']>;
|
||||
}, context: Context<ED>, params?: Object) => Promise<number>;
|
||||
}
|
||||
export interface CreateTriggerInTxn<ED extends EntityDict, T extends keyof ED> extends CreateTriggerBase<ED, T> {
|
||||
export interface CreateTriggerInTxn<ED extends EntityDict, T extends keyof ED, Cxt extends Context<ED>> extends CreateTriggerBase<ED, T, Cxt> {
|
||||
when: 'before' | 'after';
|
||||
}
|
||||
export interface CreateTriggerCrossTxn<ED extends EntityDict, T extends keyof ED> extends CreateTriggerBase<ED, T> {
|
||||
export interface CreateTriggerCrossTxn<ED extends EntityDict, T extends keyof ED, Cxt extends Context<ED>> extends CreateTriggerBase<ED, T, Cxt> {
|
||||
when: 'commit';
|
||||
strict?: 'takeEasy' | 'makeSure';
|
||||
}
|
||||
export declare type CreateTrigger<ED extends EntityDict, T extends keyof ED> = CreateTriggerInTxn<ED, T> | CreateTriggerCrossTxn<ED, T>;
|
||||
export interface UpdateTriggerBase<ED extends EntityDict, T extends keyof ED> {
|
||||
export declare type CreateTrigger<ED extends EntityDict, T extends keyof ED, Cxt extends Context<ED>> = CreateTriggerInTxn<ED, T, Cxt> | CreateTriggerCrossTxn<ED, T, Cxt>;
|
||||
export interface UpdateTriggerBase<ED extends EntityDict, T extends keyof ED, Cxt extends Context<ED>> {
|
||||
entity: T;
|
||||
name: string;
|
||||
action: Exclude<ED[T]['Action'], GenericAction> | 'update' | Array<Exclude<ED[T]['Action'], GenericAction> | 'update'>;
|
||||
|
|
@ -27,33 +27,33 @@ export interface UpdateTriggerBase<ED extends EntityDict, T extends keyof ED> {
|
|||
check?: (operation: DeduceUpdateOperation<ED[T]['Schema']>) => boolean;
|
||||
fn: (event: {
|
||||
operation: DeduceUpdateOperation<ED[T]['Schema']>;
|
||||
}, context: Context<ED>, params?: Object) => Promise<number>;
|
||||
}, context: Cxt, params?: Object) => Promise<number>;
|
||||
}
|
||||
export interface UpdateTriggerInTxn<ED extends EntityDict, T extends keyof ED> extends UpdateTriggerBase<ED, T> {
|
||||
export interface UpdateTriggerInTxn<ED extends EntityDict, T extends keyof ED, Cxt extends Context<ED>> extends UpdateTriggerBase<ED, T, Cxt> {
|
||||
when: 'before' | 'after';
|
||||
}
|
||||
export interface UpdateTriggerCrossTxn<ED extends EntityDict, T extends keyof ED> extends UpdateTriggerBase<ED, T> {
|
||||
export interface UpdateTriggerCrossTxn<ED extends EntityDict, T extends keyof ED, Cxt extends Context<ED>> extends UpdateTriggerBase<ED, T, Cxt> {
|
||||
when: 'commit';
|
||||
strict?: 'takeEasy' | 'makeSure';
|
||||
}
|
||||
export declare type UpdateTrigger<ED extends EntityDict, T extends keyof ED> = UpdateTriggerInTxn<ED, T> | UpdateTriggerCrossTxn<ED, T>;
|
||||
export interface RemoveTriggerBase<ED extends EntityDict, T extends keyof ED> {
|
||||
export declare type UpdateTrigger<ED extends EntityDict, T extends keyof ED, Cxt extends Context<ED>> = UpdateTriggerInTxn<ED, T, Cxt> | UpdateTriggerCrossTxn<ED, T, Cxt>;
|
||||
export interface RemoveTriggerBase<ED extends EntityDict, T extends keyof ED, Cxt extends Context<ED>> {
|
||||
entity: T;
|
||||
name: string;
|
||||
action: 'remove';
|
||||
check?: (operation: DeduceRemoveOperation<ED[T]['Schema']>) => boolean;
|
||||
fn: (event: {
|
||||
operation: DeduceRemoveOperation<ED[T]['Schema']>;
|
||||
}, context: Context<ED>, params?: Object) => Promise<number>;
|
||||
}, context: Cxt, params?: Object) => Promise<number>;
|
||||
}
|
||||
export interface RemoveTriggerInTxn<ED extends EntityDict, T extends keyof ED> extends RemoveTriggerBase<ED, T> {
|
||||
export interface RemoveTriggerInTxn<ED extends EntityDict, T extends keyof ED, Cxt extends Context<ED>> extends RemoveTriggerBase<ED, T, Cxt> {
|
||||
when: 'before' | 'after';
|
||||
}
|
||||
export interface RemoveTriggerCrossTxn<ED extends EntityDict, T extends keyof ED> extends RemoveTriggerBase<ED, T> {
|
||||
export interface RemoveTriggerCrossTxn<ED extends EntityDict, T extends keyof ED, Cxt extends Context<ED>> extends RemoveTriggerBase<ED, T, Cxt> {
|
||||
when: 'commit';
|
||||
strict?: 'takeEasy' | 'makeSure';
|
||||
}
|
||||
export declare type RemoveTrigger<ED extends EntityDict, T extends keyof ED> = RemoveTriggerInTxn<ED, T> | RemoveTriggerCrossTxn<ED, T>;
|
||||
export declare type RemoveTrigger<ED extends EntityDict, T extends keyof ED, Cxt extends Context<ED>> = RemoveTriggerInTxn<ED, T, Cxt> | RemoveTriggerCrossTxn<ED, T, Cxt>;
|
||||
export interface SelectTriggerBase<ED extends EntityDict, T extends keyof ED> {
|
||||
entity: T;
|
||||
name: string;
|
||||
|
|
@ -63,21 +63,21 @@ export interface SelectTriggerBase<ED extends EntityDict, T extends keyof ED> {
|
|||
* selection似乎不需要支持跨事务?没想清楚
|
||||
* todo by Xc
|
||||
*/
|
||||
export interface SelectTriggerBefore<ED extends EntityDict, T extends keyof ED> extends SelectTriggerBase<ED, T> {
|
||||
export interface SelectTriggerBefore<ED extends EntityDict, T extends keyof ED, Cxt extends Context<ED>> extends SelectTriggerBase<ED, T> {
|
||||
when: 'before';
|
||||
fn: (event: {
|
||||
operation: DeduceSelection<ED[T]['Schema']>;
|
||||
}, context: Context<ED>, params?: Object) => Promise<number>;
|
||||
}, context: Cxt, params?: Object) => Promise<number>;
|
||||
}
|
||||
export interface SelectTriggerAfter<ED extends EntityDict, T extends keyof ED> extends SelectTriggerBase<ED, T> {
|
||||
export interface SelectTriggerAfter<ED extends EntityDict, T extends keyof ED, Cxt extends Context<ED>> extends SelectTriggerBase<ED, T> {
|
||||
when: 'after';
|
||||
fn: <S extends ED[T]['Selection']>(event: {
|
||||
operation: S;
|
||||
result: SelectionResult<ED[T]['Schema'], S['data']>;
|
||||
}, context: Context<ED>, params?: Object) => Promise<number>;
|
||||
}, context: Cxt, params?: Object) => Promise<number>;
|
||||
}
|
||||
export declare type SelectTrigger<ED extends EntityDict, T extends keyof ED> = SelectTriggerBefore<ED, T> | SelectTriggerAfter<ED, T>;
|
||||
export declare type Trigger<ED extends EntityDict, T extends keyof ED> = CreateTrigger<ED, T> | UpdateTrigger<ED, T> | RemoveTrigger<ED, T> | SelectTrigger<ED, T>;
|
||||
export declare type SelectTrigger<ED extends EntityDict, T extends keyof ED, Cxt extends Context<ED>> = SelectTriggerBefore<ED, T, Cxt> | SelectTriggerAfter<ED, T, Cxt>;
|
||||
export declare type Trigger<ED extends EntityDict, T extends keyof ED, Cxt extends Context<ED>> = CreateTrigger<ED, T, Cxt> | UpdateTrigger<ED, T, Cxt> | RemoveTrigger<ED, T, Cxt> | SelectTrigger<ED, T, Cxt>;
|
||||
export interface TriggerEntityShape extends EntityShape {
|
||||
$$triggerData$$?: {
|
||||
name: string;
|
||||
|
|
@ -85,11 +85,11 @@ export interface TriggerEntityShape extends EntityShape {
|
|||
};
|
||||
$$triggerTimestamp$$?: number;
|
||||
}
|
||||
export declare abstract class Executor<ED extends EntityDict> {
|
||||
export declare abstract class Executor<ED extends EntityDict, Cxt extends Context<ED>> {
|
||||
static dataAttr: TriggerDataAttribute;
|
||||
static timestampAttr: TriggerTimestampAttribute;
|
||||
abstract registerTrigger<T extends keyof ED>(trigger: Trigger<ED, T>): void;
|
||||
abstract preOperation<T extends keyof ED>(entity: T, operation: ED[T]['Operation'], context: Context<ED>): Promise<void>;
|
||||
abstract postOperation<T extends keyof ED>(entity: T, operation: ED[T]['Operation'], context: Context<ED>): Promise<void>;
|
||||
abstract checkpoint(context: Context<ED>, timestamp: number): Promise<number>;
|
||||
abstract registerTrigger<T extends keyof ED>(trigger: Trigger<ED, T, Cxt>): void;
|
||||
abstract preOperation<T extends keyof ED>(entity: T, operation: ED[T]['Operation'], context: Cxt): Promise<void>;
|
||||
abstract postOperation<T extends keyof ED>(entity: T, operation: ED[T]['Operation'], context: Cxt): Promise<void>;
|
||||
abstract checkpoint(context: Cxt, timestamp: number): Promise<number>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,3 +12,4 @@ export * from './Polyfill';
|
|||
export * from './RowStore';
|
||||
export * from './Storage';
|
||||
export * from './Trigger';
|
||||
export * from './Exception';
|
||||
|
|
|
|||
|
|
@ -24,3 +24,4 @@ __exportStar(require("./Polyfill"), exports);
|
|||
__exportStar(require("./RowStore"), exports);
|
||||
__exportStar(require("./Storage"), exports);
|
||||
__exportStar(require("./Trigger"), exports);
|
||||
__exportStar(require("./Exception"), exports);
|
||||
|
|
|
|||
|
|
@ -70,6 +70,13 @@ const ActionAsts: {
|
|||
};
|
||||
} = {};
|
||||
|
||||
const SchemaAsts: {
|
||||
[module: string]: {
|
||||
statements: Array<ts.Statement>;
|
||||
sourceFile: ts.SourceFile;
|
||||
};
|
||||
} = {};
|
||||
|
||||
function addRelationship(many: string, one: string, key: string) {
|
||||
const { [many]: manySet } = ManyToOne;
|
||||
const one2 = one === 'Schema' ? many : one;
|
||||
|
|
@ -105,7 +112,7 @@ function createForeignRef(entity: string, foreignKey: string, ref: string) {
|
|||
|
||||
function pushStatementIntoActionAst(
|
||||
moduleName: string,
|
||||
node: ts.TypeAliasDeclaration | ts.VariableStatement,
|
||||
node: ts.Statement,
|
||||
sourceFile: ts.SourceFile) {
|
||||
if (ActionAsts[moduleName]) {
|
||||
ActionAsts[moduleName].statements.push(node);
|
||||
|
|
@ -121,6 +128,20 @@ function pushStatementIntoActionAst(
|
|||
}
|
||||
}
|
||||
|
||||
function pushStatementIntoSchemaAst(moduleName: string, statement: ts.Statement, sourceFile: ts.SourceFile) {
|
||||
if (SchemaAsts[moduleName]) {
|
||||
SchemaAsts[moduleName].statements.push(statement);
|
||||
}
|
||||
else {
|
||||
assign(SchemaAsts, {
|
||||
[moduleName]: {
|
||||
statements: [statement],
|
||||
sourceFile,
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查ActionDef是否满足合法的定义
|
||||
* 1、ActionDef, Action, State三者命名是否一致
|
||||
|
|
@ -303,6 +324,7 @@ function analyzeEntity(filename: string, path: string, program: ts.Program) {
|
|||
const schemaAttrs: ts.TypeElement[] = [];
|
||||
let hasFulltextIndex: boolean = false;
|
||||
let indexes: ts.ArrayLiteralExpression;
|
||||
let beforeSchema = true;
|
||||
ts.forEachChild(sourceFile!, (node) => {
|
||||
if (ts.isImportDeclaration(node)) {
|
||||
const entityImported = getEntityImported(node, filename);
|
||||
|
|
@ -398,6 +420,11 @@ function analyzeEntity(filename: string, path: string, program: ts.Program) {
|
|||
[moduleName]: 1,
|
||||
});
|
||||
}
|
||||
beforeSchema = false;
|
||||
}
|
||||
else if (beforeSchema) {
|
||||
// 本地规定的一些形状定义,直接使用
|
||||
pushStatementIntoSchemaAst(moduleName, node, sourceFile!);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -439,8 +466,7 @@ function analyzeEntity(filename: string, path: string, program: ts.Program) {
|
|||
);
|
||||
dealWithActions(moduleName, filename, node.type, program, schemaAttrs);
|
||||
}
|
||||
|
||||
if (node.name.text === 'Relation') {
|
||||
else if (node.name.text === 'Relation') {
|
||||
// 增加userXXX对象的描述
|
||||
if (ts.isLiteralTypeNode(node.type)) {
|
||||
assert(ts.isStringLiteral(node.type.literal));
|
||||
|
|
@ -492,6 +518,10 @@ function analyzeEntity(filename: string, path: string, program: ts.Program) {
|
|||
addRelationship(relationEntityName, 'User', 'user');
|
||||
addRelationship(relationEntityName, moduleName, entityLc);
|
||||
}
|
||||
else if (beforeSchema) {
|
||||
// 本地规定的一些形状定义,直接使用
|
||||
pushStatementIntoSchemaAst(moduleName, node, sourceFile!);
|
||||
}
|
||||
}
|
||||
|
||||
if (ts.isVariableStatement(node)) {
|
||||
|
|
@ -958,6 +988,11 @@ function constructSchema(statements: Array<ts.Statement>, entity: string) {
|
|||
}
|
||||
);
|
||||
|
||||
// 在这里把需要直接拷贝过来的语句写入
|
||||
if (SchemaAsts[entity]) {
|
||||
statements.push(...SchemaAsts[entity].statements);
|
||||
}
|
||||
|
||||
// if (keys(foreignKeySet).length > 0) {
|
||||
// for (const fkItem in foreignKeySet) {
|
||||
// const entityLc = fkItem.slice(0, 1).toLowerCase().concat(fkItem.slice(1));
|
||||
|
|
@ -1212,9 +1247,7 @@ function constructFilter(statements: Array<ts.Statement>, entity: string) {
|
|||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
assert(ts.isUnionTypeNode(type!) && ts.isLiteralTypeNode(type.types[0]) || ts.isLiteralTypeNode(type!));
|
||||
|
||||
else if (ts.isUnionTypeNode(type!) && ts.isLiteralTypeNode(type.types[0]) || ts.isLiteralTypeNode(type!)) {
|
||||
members.push(
|
||||
factory.createPropertySignature(
|
||||
undefined,
|
||||
|
|
@ -1229,6 +1262,9 @@ function constructFilter(statements: Array<ts.Statement>, entity: string) {
|
|||
)
|
||||
);
|
||||
}
|
||||
else {
|
||||
// 此时应当是引用本地定义的shape
|
||||
}
|
||||
}
|
||||
|
||||
// type AttrFilter = {};
|
||||
|
|
@ -1398,7 +1434,8 @@ function constructProjection(statements: Array<ts.Statement>, entity: string) {
|
|||
}
|
||||
}
|
||||
else {
|
||||
assert(ts.isUnionTypeNode(type!) && ts.isLiteralTypeNode(type.types[0]) || ts.isLiteralTypeNode(type!));
|
||||
// 增加了本身object的shape定义
|
||||
// assert(ts.isUnionTypeNode(type!) && ts.isLiteralTypeNode(type.types[0]) || ts.isLiteralTypeNode(type!));
|
||||
properties.push(
|
||||
[name, false, undefined]
|
||||
)
|
||||
|
|
@ -1840,8 +1877,7 @@ function constructSorter(statements: Array<ts.Statement>, entity: string) {
|
|||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
assert(ts.isUnionTypeNode(type!) && ts.isLiteralTypeNode(type.types[0]) || ts.isLiteralTypeNode(type!));
|
||||
else if (ts.isUnionTypeNode(type!) && ts.isLiteralTypeNode(type.types[0]) || ts.isLiteralTypeNode(type!)) {
|
||||
members.push(
|
||||
factory.createPropertySignature(
|
||||
undefined,
|
||||
|
|
@ -1851,6 +1887,9 @@ function constructSorter(statements: Array<ts.Statement>, entity: string) {
|
|||
)
|
||||
);
|
||||
}
|
||||
else {
|
||||
// 本地规定的shape,非结构化属性不参与排序
|
||||
}
|
||||
}
|
||||
|
||||
if (ReversePointerRelations[entity]) {
|
||||
|
|
@ -4118,94 +4157,114 @@ function constructAttributes(entity: string): ts.PropertyAssignment[] {
|
|||
}
|
||||
else {
|
||||
if (ts.isUnionTypeNode(type!)) {
|
||||
assert(ts.isLiteralTypeNode(type.types[0]));
|
||||
if (ts.isStringLiteral(type.types[0].literal)) {
|
||||
attrAssignments.push(
|
||||
factory.createPropertyAssignment(
|
||||
factory.createIdentifier("type"),
|
||||
factory.createStringLiteral("varchar")
|
||||
),
|
||||
factory.createPropertyAssignment(
|
||||
factory.createIdentifier("params"),
|
||||
factory.createObjectLiteralExpression(
|
||||
[factory.createPropertyAssignment(
|
||||
factory.createIdentifier("length"),
|
||||
factory.createNumericLiteral(STRING_LITERAL_MAX_LENGTH)
|
||||
)],
|
||||
true
|
||||
if (ts.isLiteralTypeNode(type.types[0])) {
|
||||
if (ts.isStringLiteral(type.types[0].literal)) {
|
||||
attrAssignments.push(
|
||||
factory.createPropertyAssignment(
|
||||
factory.createIdentifier("type"),
|
||||
factory.createStringLiteral("varchar")
|
||||
),
|
||||
factory.createPropertyAssignment(
|
||||
factory.createIdentifier("params"),
|
||||
factory.createObjectLiteralExpression(
|
||||
[factory.createPropertyAssignment(
|
||||
factory.createIdentifier("length"),
|
||||
factory.createNumericLiteral(STRING_LITERAL_MAX_LENGTH)
|
||||
)],
|
||||
true
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
);
|
||||
}
|
||||
else {
|
||||
assert(ts.isNumericLiteral(type.types[0].literal));
|
||||
attrAssignments.push(
|
||||
factory.createPropertyAssignment(
|
||||
factory.createIdentifier("type"),
|
||||
factory.createStringLiteral("int")
|
||||
),
|
||||
factory.createPropertyAssignment(
|
||||
factory.createIdentifier("params"),
|
||||
factory.createObjectLiteralExpression(
|
||||
[
|
||||
factory.createPropertyAssignment(
|
||||
factory.createIdentifier("precision"),
|
||||
factory.createNumericLiteral(NUMERICAL_LITERL_DEFAULT_PRECISION)
|
||||
),
|
||||
factory.createPropertyAssignment(
|
||||
factory.createIdentifier("scale"),
|
||||
factory.createNumericLiteral(NUMERICAL_LITERL_DEFAULT_SCALE)
|
||||
)
|
||||
],
|
||||
true
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
assert(ts.isNumericLiteral(type.types[0].literal));
|
||||
// 否则是本地规定的shape,直接用object
|
||||
attrAssignments.push(
|
||||
factory.createPropertyAssignment(
|
||||
factory.createIdentifier("type"),
|
||||
factory.createStringLiteral("int")
|
||||
factory.createStringLiteral("object")
|
||||
),
|
||||
factory.createPropertyAssignment(
|
||||
factory.createIdentifier("params"),
|
||||
factory.createObjectLiteralExpression(
|
||||
[
|
||||
factory.createPropertyAssignment(
|
||||
factory.createIdentifier("precision"),
|
||||
factory.createNumericLiteral(NUMERICAL_LITERL_DEFAULT_PRECISION)
|
||||
),
|
||||
factory.createPropertyAssignment(
|
||||
factory.createIdentifier("scale"),
|
||||
factory.createNumericLiteral(NUMERICAL_LITERL_DEFAULT_SCALE)
|
||||
)
|
||||
],
|
||||
true
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
assert(ts.isLiteralTypeNode(type!), `${entity}中的属性${(<ts.Identifier>name).text}有非法的属性类型定义`);
|
||||
if (ts.isStringLiteral(type.literal)) {
|
||||
attrAssignments.push(
|
||||
factory.createPropertyAssignment(
|
||||
factory.createIdentifier("type"),
|
||||
factory.createStringLiteral("varchar")
|
||||
),
|
||||
factory.createPropertyAssignment(
|
||||
factory.createIdentifier("params"),
|
||||
factory.createObjectLiteralExpression(
|
||||
[factory.createPropertyAssignment(
|
||||
factory.createIdentifier("length"),
|
||||
factory.createNumericLiteral(STRING_LITERAL_MAX_LENGTH)
|
||||
)],
|
||||
true
|
||||
if (ts.isLiteralTypeNode(type!)) {
|
||||
if (ts.isStringLiteral(type.literal)) {
|
||||
attrAssignments.push(
|
||||
factory.createPropertyAssignment(
|
||||
factory.createIdentifier("type"),
|
||||
factory.createStringLiteral("varchar")
|
||||
),
|
||||
factory.createPropertyAssignment(
|
||||
factory.createIdentifier("params"),
|
||||
factory.createObjectLiteralExpression(
|
||||
[factory.createPropertyAssignment(
|
||||
factory.createIdentifier("length"),
|
||||
factory.createNumericLiteral(STRING_LITERAL_MAX_LENGTH)
|
||||
)],
|
||||
true
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
);
|
||||
}
|
||||
else {
|
||||
assert(ts.isNumericLiteral(type.literal));
|
||||
attrAssignments.push(
|
||||
factory.createPropertyAssignment(
|
||||
factory.createIdentifier("type"),
|
||||
factory.createStringLiteral("precision")
|
||||
),
|
||||
factory.createPropertyAssignment(
|
||||
factory.createIdentifier("params"),
|
||||
factory.createObjectLiteralExpression(
|
||||
[
|
||||
factory.createPropertyAssignment(
|
||||
factory.createIdentifier("precision"),
|
||||
factory.createNumericLiteral(NUMERICAL_LITERL_DEFAULT_PRECISION)
|
||||
),
|
||||
factory.createPropertyAssignment(
|
||||
factory.createIdentifier("scale"),
|
||||
factory.createNumericLiteral(NUMERICAL_LITERL_DEFAULT_SCALE)
|
||||
)
|
||||
],
|
||||
true
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
assert(ts.isNumericLiteral(type.literal));
|
||||
// 否则是本地规定的shape,直接用object
|
||||
attrAssignments.push(
|
||||
factory.createPropertyAssignment(
|
||||
factory.createIdentifier("type"),
|
||||
factory.createStringLiteral("precision")
|
||||
factory.createStringLiteral("object")
|
||||
),
|
||||
factory.createPropertyAssignment(
|
||||
factory.createIdentifier("params"),
|
||||
factory.createObjectLiteralExpression(
|
||||
[
|
||||
factory.createPropertyAssignment(
|
||||
factory.createIdentifier("precision"),
|
||||
factory.createNumericLiteral(NUMERICAL_LITERL_DEFAULT_PRECISION)
|
||||
),
|
||||
factory.createPropertyAssignment(
|
||||
factory.createIdentifier("scale"),
|
||||
factory.createNumericLiteral(NUMERICAL_LITERL_DEFAULT_SCALE)
|
||||
)
|
||||
],
|
||||
true
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -4489,6 +4548,6 @@ export function buildSchema(outputDir: string): void {
|
|||
outputStorage(outputDir, printer);
|
||||
|
||||
//if (!process.env.COMPLING_BASE_ENTITY_DICT) {
|
||||
outputPackageJson(outputDir);
|
||||
outputPackageJson(outputDir);
|
||||
//}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,35 +2,33 @@ import assert from "assert";
|
|||
import { assign } from "lodash";
|
||||
import { Context } from '../types/Context';
|
||||
import { DeduceCreateOperation, DeduceCreateSingleOperation, DeduceFilter, DeduceRemoveOperation, DeduceSelection,
|
||||
DeduceUpdateOperation, EntityDef, EntityShape, OperateParams, SelectionResult } from "../types/Entity";
|
||||
DeduceUpdateOperation, EntityDict, EntityShape, OperateParams, SelectionResult } from "../types/Entity";
|
||||
import { RowStore } from '../types/RowStore';
|
||||
import { StorageSchema } from '../types/Storage';
|
||||
import { addFilterSegment } from "./filter";
|
||||
import { judgeRelation } from "./relation";
|
||||
|
||||
/**这个用来处理级联的select和update,对不同能力的 */
|
||||
export abstract class CascadeStore<ED extends {
|
||||
[E: string]: EntityDef;
|
||||
}> extends RowStore<ED> {
|
||||
export abstract class CascadeStore<ED extends EntityDict, Cxt extends Context<ED>> extends RowStore<ED, Cxt> {
|
||||
constructor(storageSchema: StorageSchema<ED>) {
|
||||
super(storageSchema);
|
||||
}
|
||||
protected abstract selectAbjointRow<T extends keyof ED>(
|
||||
entity: T,
|
||||
selection: Omit<ED[T]['Selection'], 'indexFrom' | 'count' | 'data' | 'sorter'>,
|
||||
context: Context<ED>,
|
||||
context: Cxt,
|
||||
params?: OperateParams): Promise<Array<ED[T]['OpSchema']>>;
|
||||
|
||||
protected abstract updateAbjointRow<T extends keyof ED>(
|
||||
entity: T,
|
||||
operation: DeduceCreateSingleOperation<ED[T]['Schema']> | DeduceUpdateOperation<ED[T]['Schema']> | DeduceRemoveOperation<ED[T]['Schema']>,
|
||||
context: Context<ED>,
|
||||
context: Cxt,
|
||||
params?: OperateParams): Promise<void>;
|
||||
|
||||
protected async cascadeSelect<T extends keyof ED>(
|
||||
entity: T,
|
||||
selection: ED[T]['Selection'],
|
||||
context: Context<ED>, params?: OperateParams): Promise<Array<ED[T]['Schema']>> {
|
||||
context: Cxt, params?: OperateParams): Promise<Array<ED[T]['Schema']>> {
|
||||
const { data } = selection;
|
||||
|
||||
const projection: ED[T]['Selection']['data'] = {};
|
||||
|
|
@ -166,7 +164,7 @@ export abstract class CascadeStore<ED extends {
|
|||
protected async cascadeUpdate<T extends keyof ED>(
|
||||
entity: T,
|
||||
operation: DeduceCreateOperation<ED[T]['Schema']> | DeduceUpdateOperation<ED[T]['Schema']> | DeduceRemoveOperation<ED[T]['Schema']>,
|
||||
context: Context<ED>,
|
||||
context: Cxt,
|
||||
params?: OperateParams): Promise<void> {
|
||||
const { action, data, filter } = operation;
|
||||
const opData = {};
|
||||
|
|
|
|||
|
|
@ -19,28 +19,30 @@ import { Trigger, Executor, CreateTriggerCrossTxn, CreateTrigger, CreateTriggerI
|
|||
'stat': 'select',
|
||||
}; */
|
||||
|
||||
export class TriggerExecutor<ED extends EntityDict> extends Executor<ED> {
|
||||
export class TriggerExecutor<ED extends EntityDict, Cxt extends Context<ED>> extends Executor<ED, Cxt> {
|
||||
private triggerMap: {
|
||||
[T in keyof ED]?: {
|
||||
[A: string]: Array<Trigger<ED, T>>;
|
||||
[A: string]: Array<Trigger<ED, T, Cxt>>;
|
||||
};
|
||||
};
|
||||
private triggerNameMap: {
|
||||
[N: string]: Trigger<ED, keyof ED>;
|
||||
[N: string]: Trigger<ED, keyof ED, Cxt>;
|
||||
};
|
||||
private volatileEntities: Array<keyof ED>;
|
||||
|
||||
private logger: Logger;
|
||||
private contextBuilder: () => Cxt;
|
||||
|
||||
constructor(logger: Logger = console) {
|
||||
constructor(contextBuilder: () => Cxt, logger: Logger = console) {
|
||||
super();
|
||||
this.contextBuilder = contextBuilder;
|
||||
this.logger = logger;
|
||||
this.triggerMap = {};
|
||||
this.triggerNameMap = {};
|
||||
this.volatileEntities = [];
|
||||
}
|
||||
|
||||
registerChecker<T extends keyof ED>(checker: Checker<ED, T>): void {
|
||||
registerChecker<T extends keyof ED>(checker: Checker<ED, T, Cxt>): void {
|
||||
const { entity, action, checker: checkFn } = checker;
|
||||
const ActionNameMatrix: Record<string, string> = {
|
||||
'create': '创建',
|
||||
|
|
@ -55,11 +57,11 @@ export class TriggerExecutor<ED extends EntityDict> extends Executor<ED> {
|
|||
action,
|
||||
fn: checkFn,
|
||||
when: 'before',
|
||||
} as CreateTriggerInTxn<ED, T>;
|
||||
} as CreateTriggerInTxn<ED, T, Cxt>;
|
||||
this.registerTrigger(trigger);
|
||||
}
|
||||
|
||||
registerTrigger<T extends keyof ED>(trigger: Trigger<ED, T>): void {
|
||||
registerTrigger<T extends keyof ED>(trigger: Trigger<ED, T, Cxt>): void {
|
||||
// trigger的两种访问方式: by name, by entity/action
|
||||
if (this.triggerNameMap.hasOwnProperty(trigger.name)) {
|
||||
throw new Error(`不可有同名的触发器「${trigger.name}」`);
|
||||
|
|
@ -102,7 +104,7 @@ export class TriggerExecutor<ED extends EntityDict> extends Executor<ED> {
|
|||
}
|
||||
}
|
||||
|
||||
unregisterTrigger<T extends keyof ED>(trigger: Trigger<ED, T>): void {
|
||||
unregisterTrigger<T extends keyof ED>(trigger: Trigger<ED, T, Cxt>): void {
|
||||
assert(trigger.when !== 'commit' || trigger.strict !== 'makeSure', 'could not remove strict volatile triggers');
|
||||
|
||||
const removeTrigger = (action: string) => {
|
||||
|
|
@ -126,11 +128,11 @@ export class TriggerExecutor<ED extends EntityDict> extends Executor<ED> {
|
|||
private async preCommitTrigger<T extends keyof ED>(
|
||||
entity: T,
|
||||
operation: ED[T]['Operation'],
|
||||
trigger: Trigger<ED, T>,
|
||||
context: Context<ED>,
|
||||
trigger: Trigger<ED, T, Cxt>,
|
||||
context: Cxt,
|
||||
) {
|
||||
assert(trigger.action !== 'select');
|
||||
if ((trigger as CreateTriggerCrossTxn<ED, T>).strict === 'makeSure') {
|
||||
if ((trigger as CreateTriggerCrossTxn<ED, T, Cxt>).strict === 'makeSure') {
|
||||
switch (operation.action) {
|
||||
case 'create': {
|
||||
if (operation.data.hasOwnProperty(Executor.dataAttr) || operation.data.hasOwnProperty(Executor.timestampAttr)) {
|
||||
|
|
@ -179,7 +181,7 @@ export class TriggerExecutor<ED extends EntityDict> extends Executor<ED> {
|
|||
async preOperation<T extends keyof ED>(
|
||||
entity: T,
|
||||
operation: ED[T]['Operation'],
|
||||
context: Context<ED>
|
||||
context: Cxt
|
||||
): Promise<void> {
|
||||
const { action } = operation;
|
||||
const triggers = this.triggerMap[entity] && this.triggerMap[entity]![action].filter(
|
||||
|
|
@ -187,18 +189,18 @@ export class TriggerExecutor<ED extends EntityDict> extends Executor<ED> {
|
|||
);
|
||||
if (triggers) {
|
||||
const preTriggers = triggers.filter(
|
||||
ele => ele.when === 'before' && (!(ele as CreateTrigger<ED, T>).check || (ele as CreateTrigger<ED, T>).check!(operation as DeduceCreateOperation<ED[T]['Schema']>))
|
||||
ele => ele.when === 'before' && (!(ele as CreateTrigger<ED, T, Cxt>).check || (ele as CreateTrigger<ED, T, Cxt>).check!(operation as DeduceCreateOperation<ED[T]['Schema']>))
|
||||
);
|
||||
|
||||
for (const trigger of preTriggers) {
|
||||
const number = await (trigger as CreateTrigger<ED, T>).fn({ operation: operation as DeduceCreateOperation<ED[T]['Schema']> }, context);
|
||||
const number = await (trigger as CreateTrigger<ED, T, Cxt>).fn({ operation: operation as DeduceCreateOperation<ED[T]['Schema']> }, context);
|
||||
if (number > 0) {
|
||||
this.logger.info(`触发器「${trigger.name}」成功触发了「${number}」行数据更改`);
|
||||
}
|
||||
}
|
||||
|
||||
const commitTriggers = triggers.filter(
|
||||
ele => ele.when === 'commit' && (!(ele as CreateTrigger<ED, T>).check || (ele as CreateTrigger<ED, T>).check!(operation as DeduceCreateOperation<ED[T]['Schema']>))
|
||||
ele => ele.when === 'commit' && (!(ele as CreateTrigger<ED, T, Cxt>).check || (ele as CreateTrigger<ED, T, Cxt>).check!(operation as DeduceCreateOperation<ED[T]['Schema']>))
|
||||
);
|
||||
|
||||
for (const trigger of commitTriggers) {
|
||||
|
|
@ -208,14 +210,15 @@ export class TriggerExecutor<ED extends EntityDict> extends Executor<ED> {
|
|||
}
|
||||
|
||||
private onCommit<T extends keyof ED>(
|
||||
trigger: Trigger<ED, T>, operation: ED[T]['Operation']) {
|
||||
return async (context: Context<ED>) => {
|
||||
trigger: Trigger<ED, T, Cxt>, operation: ED[T]['Operation']) {
|
||||
return async () => {
|
||||
const context = this.contextBuilder();
|
||||
await context.begin();
|
||||
const number = await (trigger as CreateTrigger<ED, T>).fn({
|
||||
const number = await (trigger as CreateTrigger<ED, T, Cxt>).fn({
|
||||
operation: operation as DeduceCreateOperation<ED[T]['Schema']>,
|
||||
}, context);
|
||||
const { rowStore } = context;
|
||||
if ((trigger as CreateTriggerCrossTxn<ED, T>).strict === 'makeSure') {
|
||||
if ((trigger as CreateTriggerCrossTxn<ED, T, Cxt>).strict === 'makeSure') {
|
||||
// 如果是必须完成的trigger,在完成成功后要把trigger相关的属性置null;
|
||||
let filter = {};
|
||||
if (operation.action === 'create') {
|
||||
|
|
@ -252,8 +255,8 @@ export class TriggerExecutor<ED extends EntityDict> extends Executor<ED> {
|
|||
|
||||
private async postCommitTrigger<T extends keyof ED>(
|
||||
operation: ED[T]['Operation'],
|
||||
trigger: Trigger<ED, T>,
|
||||
context: Context<ED>
|
||||
trigger: Trigger<ED, T, Cxt>,
|
||||
context: Cxt
|
||||
) {
|
||||
context.on('commit', this.onCommit(trigger, operation));
|
||||
}
|
||||
|
|
@ -261,23 +264,23 @@ export class TriggerExecutor<ED extends EntityDict> extends Executor<ED> {
|
|||
async postOperation<T extends keyof ED>(
|
||||
entity: T,
|
||||
operation: ED[T]['Operation'],
|
||||
context: Context<ED>
|
||||
context: Cxt
|
||||
): Promise<void> {
|
||||
const { action } = operation;
|
||||
const triggers = this.triggerMap[entity] && this.triggerMap[entity]![action];
|
||||
if (triggers) {
|
||||
const postTriggers = triggers.filter(
|
||||
ele => ele.when === 'after' && (!(ele as CreateTrigger<ED, T>).check || (ele as CreateTrigger<ED, T>).check!(operation as DeduceCreateOperation<ED[T]['Schema']>))
|
||||
ele => ele.when === 'after' && (!(ele as CreateTrigger<ED, T, Cxt>).check || (ele as CreateTrigger<ED, T, Cxt>).check!(operation as DeduceCreateOperation<ED[T]['Schema']>))
|
||||
);
|
||||
|
||||
for (const trigger of postTriggers) {
|
||||
const number = await (trigger as CreateTrigger<ED, T>).fn({ operation: operation as DeduceCreateOperation<ED[T]['Schema']> }, context);
|
||||
const number = await (trigger as CreateTrigger<ED, T, Cxt>).fn({ operation: operation as DeduceCreateOperation<ED[T]['Schema']> }, context);
|
||||
if (number > 0) {
|
||||
this.logger.info(`触发器「${trigger.name}」成功触发了「${number}」行数据更改`);
|
||||
}
|
||||
}
|
||||
|
||||
const commitTriggers = (<Array<CreateTrigger<ED, T>>>triggers).filter(
|
||||
const commitTriggers = (<Array<CreateTrigger<ED, T, Cxt>>>triggers).filter(
|
||||
ele => ele.when === 'commit' && (!ele.check || ele.check(operation as DeduceCreateOperation<ED[T]['Schema']>))
|
||||
);
|
||||
|
||||
|
|
@ -287,7 +290,7 @@ export class TriggerExecutor<ED extends EntityDict> extends Executor<ED> {
|
|||
}
|
||||
}
|
||||
|
||||
async checkpoint(context: Context<ED>, timestamp: number): Promise<number> {
|
||||
async checkpoint(context: Cxt, timestamp: number): Promise<number> {
|
||||
let result = 0;
|
||||
const { rowStore } = context;
|
||||
for (const entity of this.volatileEntities) {
|
||||
|
|
@ -306,7 +309,7 @@ export class TriggerExecutor<ED extends EntityDict> extends Executor<ED> {
|
|||
const { $$triggerData$$ } = row;
|
||||
const { name, operation } = $$triggerData$$!;
|
||||
const trigger = this.triggerNameMap[name];
|
||||
await this.onCommit(trigger, operation as ED[typeof entity]['Operation'])(context);
|
||||
await this.onCommit(trigger, operation as ED[typeof entity]['Operation'])();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
import { EntityDict, OpRecord, RowStore, TxnOption, Context } from "../types";
|
||||
|
||||
export class UniversalContext<ED extends EntityDict> implements Context<ED> {
|
||||
rowStore: RowStore<ED>;
|
||||
rowStore: RowStore<ED, this>;
|
||||
uuid?: string;
|
||||
opRecords: OpRecord<ED>[];
|
||||
events: {
|
||||
commit: Array<(context: UniversalContext<ED>) => Promise<void>>;
|
||||
rollback: Array<(context: UniversalContext<ED>) => Promise<void>>;
|
||||
commit: Array<() => Promise<void>>;
|
||||
rollback: Array<() => Promise<void>>;
|
||||
}
|
||||
|
||||
constructor(store: RowStore<ED>) {
|
||||
constructor(store: RowStore<ED, UniversalContext<ED>>) {
|
||||
this.rowStore = store;
|
||||
this.opRecords = [];
|
||||
this.events = {
|
||||
|
|
@ -25,7 +25,7 @@ export class UniversalContext<ED extends EntityDict> implements Context<ED> {
|
|||
};
|
||||
}
|
||||
|
||||
on(event: 'commit' | 'rollback', callback: (context: UniversalContext<ED>) => Promise<void>): void {
|
||||
on(event: 'commit' | 'rollback', callback: () => Promise<void>): void {
|
||||
this.uuid && this.events[event].push(callback);
|
||||
}
|
||||
|
||||
|
|
@ -36,27 +36,21 @@ export class UniversalContext<ED extends EntityDict> implements Context<ED> {
|
|||
}
|
||||
async commit(): Promise<void> {
|
||||
if (this.uuid) {
|
||||
/**
|
||||
* todo 这里应该等到提交成功了再做 by Xc
|
||||
*/
|
||||
for(const e of this.events.commit) {
|
||||
await e(this);
|
||||
}
|
||||
await this.rowStore.commit(this.uuid!);
|
||||
this.uuid = undefined;
|
||||
for(const e of this.events.commit) {
|
||||
await e();
|
||||
}
|
||||
this.resetEvents();
|
||||
}
|
||||
}
|
||||
async rollback(): Promise<void> {
|
||||
if(this.uuid) {
|
||||
/**
|
||||
* todo 这里应该等到回滚成功了再做 by Xc
|
||||
*/
|
||||
for(const e of this.events.rollback) {
|
||||
await e(this);
|
||||
}
|
||||
await this.rowStore.rollback(this.uuid!);
|
||||
this.uuid = undefined;
|
||||
for(const e of this.events.rollback) {
|
||||
await e();
|
||||
}
|
||||
this.resetEvents();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,35 +1,23 @@
|
|||
import { EntityDict } from "../types/Entity";
|
||||
import { Context } from "./Context";
|
||||
import { CreateTriggerBase, RemoveTriggerBase, UpdateTriggerBase } from "./Trigger";
|
||||
|
||||
export class AttrIllegalError extends Error {
|
||||
private attributes: string[];
|
||||
constructor(attributes: string[], message?: string) {
|
||||
super(message);
|
||||
this.attributes = attributes;
|
||||
}
|
||||
|
||||
getAttributes() {
|
||||
return this.attributes;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
export type CreateChecker<ED extends EntityDict, T extends keyof ED> = {
|
||||
export type CreateChecker<ED extends EntityDict, T extends keyof ED, Cxt extends Context<ED>> = {
|
||||
action: 'create';
|
||||
entity: T;
|
||||
checker: CreateTriggerBase<ED, T>['fn'],
|
||||
checker: CreateTriggerBase<ED, T, Cxt>['fn'],
|
||||
};
|
||||
|
||||
export type UpdateChecker<ED extends EntityDict, T extends keyof ED> = {
|
||||
action: UpdateTriggerBase<ED, T>['action'];
|
||||
export type UpdateChecker<ED extends EntityDict, T extends keyof ED, Cxt extends Context<ED>> = {
|
||||
action: UpdateTriggerBase<ED, T, Cxt>['action'];
|
||||
entity: T;
|
||||
checker: UpdateTriggerBase<ED, T>['fn'],
|
||||
checker: UpdateTriggerBase<ED, T, Cxt>['fn'],
|
||||
};
|
||||
|
||||
export type RemoveChecker<ED extends EntityDict, T extends keyof ED> = {
|
||||
export type RemoveChecker<ED extends EntityDict, T extends keyof ED, Cxt extends Context<ED>> = {
|
||||
action: 'remove';
|
||||
entity: T;
|
||||
checker: RemoveTriggerBase<ED, T>['fn'],
|
||||
checker: RemoveTriggerBase<ED, T, Cxt>['fn'],
|
||||
};
|
||||
|
||||
export type Checker<ED extends EntityDict, T extends keyof ED> = CreateChecker<ED, T> | UpdateChecker<ED, T> | RemoveChecker<ED, T>;
|
||||
export type Checker<ED extends EntityDict, T extends keyof ED, Cxt extends Context<ED>> = CreateChecker<ED, T, Cxt> | UpdateChecker<ED, T, Cxt> | RemoveChecker<ED, T, Cxt>;
|
||||
|
|
|
|||
|
|
@ -4,11 +4,11 @@ import { RowStore } from './RowStore';
|
|||
|
||||
export interface Context<ED extends EntityDict>{
|
||||
opRecords: OpRecord<ED>[];
|
||||
rowStore: RowStore<ED>;
|
||||
rowStore: RowStore<ED, this>;
|
||||
begin(options?: object): Promise<void>;
|
||||
commit():Promise<void>;
|
||||
rollback():Promise<void>;
|
||||
getCurrentTxnId(): string | undefined;
|
||||
on(event: 'commit' | 'rollback', callback: (context: Context<ED>) => Promise<void>): void;
|
||||
on(event: 'commit' | 'rollback', callback: () => Promise<void>): void;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ export type TxnOption = {
|
|||
isolationLevel: 'repeatable read' | 'serializable';
|
||||
};
|
||||
|
||||
export abstract class RowStore<ED extends EntityDict> {
|
||||
export abstract class RowStore<ED extends EntityDict, Cxt extends Context<ED>> {
|
||||
static $$LEVEL = 'store';
|
||||
static $$CODES: OakErrorDefDict = {
|
||||
primaryKeyConfilict: [1, '主键重复'],
|
||||
|
|
@ -19,21 +19,21 @@ export abstract class RowStore<ED extends EntityDict> {
|
|||
abstract operate<T extends keyof ED>(
|
||||
entity: T,
|
||||
operation: ED[T]['Operation'],
|
||||
context: Context<ED>,
|
||||
context: Cxt,
|
||||
params?: OperateParams
|
||||
): Promise<OperationResult>;
|
||||
|
||||
abstract select<T extends keyof ED, S extends ED[T]['Selection']> (
|
||||
entity: T,
|
||||
selection: S,
|
||||
context: Context<ED>,
|
||||
context: Cxt,
|
||||
params?: Object
|
||||
): Promise<SelectionResult<ED[T]['Schema'], S['data']>>;
|
||||
|
||||
abstract count<T extends keyof ED> (
|
||||
entity: T,
|
||||
selection: Omit<ED[T]['Selection'], 'data' | 'sorter' | 'action'>,
|
||||
context: Context<ED>,
|
||||
context: Cxt,
|
||||
params?: Object
|
||||
): Promise<number>;
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { DeduceCreateOperation, DeduceRemoveOperation, DeduceSelection, DeduceUp
|
|||
import { EntityDef, EntityShape, OperationResult, SelectionResult, TriggerDataAttribute, TriggerTimestampAttribute } from "../types/Entity";
|
||||
import { Context } from "./Context";
|
||||
|
||||
export interface CreateTriggerBase<ED extends EntityDict, T extends keyof ED> {
|
||||
export interface CreateTriggerBase<ED extends EntityDict, T extends keyof ED, Cxt extends Context<ED>> {
|
||||
entity: T;
|
||||
name: string;
|
||||
action: 'create',
|
||||
|
|
@ -11,57 +11,57 @@ export interface CreateTriggerBase<ED extends EntityDict, T extends keyof ED> {
|
|||
fn: (event: { operation: DeduceCreateOperation<ED[T]['Schema']>; }, context: Context<ED>, params?: Object) => Promise<number>;
|
||||
};
|
||||
|
||||
export interface CreateTriggerInTxn<ED extends EntityDict, T extends keyof ED> extends CreateTriggerBase<ED, T> {
|
||||
export interface CreateTriggerInTxn<ED extends EntityDict, T extends keyof ED, Cxt extends Context<ED>> extends CreateTriggerBase<ED, T, Cxt> {
|
||||
when: 'before' | 'after',
|
||||
};
|
||||
|
||||
export interface CreateTriggerCrossTxn<ED extends EntityDict, T extends keyof ED> extends CreateTriggerBase<ED, T> {
|
||||
export interface CreateTriggerCrossTxn<ED extends EntityDict, T extends keyof ED, Cxt extends Context<ED>> extends CreateTriggerBase<ED, T, Cxt> {
|
||||
when: 'commit',
|
||||
strict?: 'takeEasy' | 'makeSure';
|
||||
};
|
||||
|
||||
export type CreateTrigger<ED extends EntityDict, T extends keyof ED> = CreateTriggerInTxn<ED, T> | CreateTriggerCrossTxn<ED, T>;
|
||||
export type CreateTrigger<ED extends EntityDict, T extends keyof ED, Cxt extends Context<ED>> = CreateTriggerInTxn<ED, T, Cxt> | CreateTriggerCrossTxn<ED, T, Cxt>;
|
||||
|
||||
|
||||
export interface UpdateTriggerBase<ED extends EntityDict, T extends keyof ED> {
|
||||
export interface UpdateTriggerBase<ED extends EntityDict, T extends keyof ED, Cxt extends Context<ED>> {
|
||||
entity: T;
|
||||
name: string;
|
||||
action: Exclude<ED[T]['Action'], GenericAction> | 'update' | Array<Exclude<ED[T]['Action'], GenericAction> | 'update'>,
|
||||
attributes?: keyof ED[T]['OpSchema'] | Array<keyof ED[T]['OpSchema']>;
|
||||
check?: (operation: DeduceUpdateOperation<ED[T]['Schema']>) => boolean;
|
||||
fn: (event: { operation: DeduceUpdateOperation<ED[T]['Schema']> }, context: Context<ED>, params?: Object) => Promise<number>;
|
||||
fn: (event: { operation: DeduceUpdateOperation<ED[T]['Schema']> }, context: Cxt, params?: Object) => Promise<number>;
|
||||
};
|
||||
|
||||
export interface UpdateTriggerInTxn<ED extends EntityDict, T extends keyof ED> extends UpdateTriggerBase<ED, T> {
|
||||
export interface UpdateTriggerInTxn<ED extends EntityDict, T extends keyof ED, Cxt extends Context<ED>> extends UpdateTriggerBase<ED, T, Cxt> {
|
||||
when: 'before' | 'after',
|
||||
};
|
||||
|
||||
export interface UpdateTriggerCrossTxn<ED extends EntityDict, T extends keyof ED> extends UpdateTriggerBase<ED, T> {
|
||||
export interface UpdateTriggerCrossTxn<ED extends EntityDict, T extends keyof ED, Cxt extends Context<ED>> extends UpdateTriggerBase<ED, T, Cxt> {
|
||||
when: 'commit',
|
||||
strict?: 'takeEasy' | 'makeSure';
|
||||
};
|
||||
|
||||
export type UpdateTrigger<ED extends EntityDict, T extends keyof ED> = UpdateTriggerInTxn<ED, T> | UpdateTriggerCrossTxn<ED, T>;
|
||||
export type UpdateTrigger<ED extends EntityDict, T extends keyof ED, Cxt extends Context<ED>> = UpdateTriggerInTxn<ED, T, Cxt> | UpdateTriggerCrossTxn<ED, T, Cxt>;
|
||||
|
||||
|
||||
export interface RemoveTriggerBase<ED extends EntityDict, T extends keyof ED> {
|
||||
export interface RemoveTriggerBase<ED extends EntityDict, T extends keyof ED, Cxt extends Context<ED>> {
|
||||
entity: T;
|
||||
name: string;
|
||||
action: 'remove',
|
||||
check?: (operation: DeduceRemoveOperation<ED[T]['Schema']>) => boolean;
|
||||
fn: (event: { operation: DeduceRemoveOperation<ED[T]['Schema']> }, context: Context<ED>, params?: Object) => Promise<number>;
|
||||
fn: (event: { operation: DeduceRemoveOperation<ED[T]['Schema']> }, context: Cxt, params?: Object) => Promise<number>;
|
||||
};
|
||||
|
||||
export interface RemoveTriggerInTxn<ED extends EntityDict, T extends keyof ED> extends RemoveTriggerBase<ED, T> {
|
||||
export interface RemoveTriggerInTxn<ED extends EntityDict, T extends keyof ED, Cxt extends Context<ED>> extends RemoveTriggerBase<ED, T, Cxt> {
|
||||
when: 'before' | 'after',
|
||||
};
|
||||
|
||||
export interface RemoveTriggerCrossTxn<ED extends EntityDict, T extends keyof ED> extends RemoveTriggerBase<ED, T> {
|
||||
export interface RemoveTriggerCrossTxn<ED extends EntityDict, T extends keyof ED, Cxt extends Context<ED>> extends RemoveTriggerBase<ED, T, Cxt> {
|
||||
when: 'commit',
|
||||
strict?: 'takeEasy' | 'makeSure';
|
||||
};
|
||||
|
||||
export type RemoveTrigger<ED extends EntityDict, T extends keyof ED> = RemoveTriggerInTxn<ED, T> | RemoveTriggerCrossTxn<ED, T>;
|
||||
export type RemoveTrigger<ED extends EntityDict, T extends keyof ED, Cxt extends Context<ED>> = RemoveTriggerInTxn<ED, T, Cxt> | RemoveTriggerCrossTxn<ED, T, Cxt>;
|
||||
|
||||
|
||||
export interface SelectTriggerBase<ED extends EntityDict, T extends keyof ED> {
|
||||
|
|
@ -74,22 +74,23 @@ export interface SelectTriggerBase<ED extends EntityDict, T extends keyof ED> {
|
|||
* selection似乎不需要支持跨事务?没想清楚
|
||||
* todo by Xc
|
||||
*/
|
||||
export interface SelectTriggerBefore<ED extends EntityDict, T extends keyof ED> extends SelectTriggerBase<ED, T> {
|
||||
export interface SelectTriggerBefore<ED extends EntityDict, T extends keyof ED, Cxt extends Context<ED>> extends SelectTriggerBase<ED, T> {
|
||||
when: 'before';
|
||||
fn: (event: { operation: DeduceSelection<ED[T]['Schema']> }, context: Context<ED>, params?: Object) => Promise<number>;
|
||||
fn: (event: { operation: DeduceSelection<ED[T]['Schema']> }, context: Cxt, params?: Object) => Promise<number>;
|
||||
};
|
||||
|
||||
export interface SelectTriggerAfter<ED extends EntityDict, T extends keyof ED> extends SelectTriggerBase<ED, T> {
|
||||
export interface SelectTriggerAfter<ED extends EntityDict, T extends keyof ED, Cxt extends Context<ED>> extends SelectTriggerBase<ED, T> {
|
||||
when: 'after',
|
||||
fn: <S extends ED[T]['Selection']>(event: {
|
||||
operation: S;
|
||||
result: SelectionResult<ED[T]['Schema'], S['data']>;
|
||||
}, context: Context<ED>, params?: Object) => Promise<number>;
|
||||
}, context: Cxt, params?: Object) => Promise<number>;
|
||||
};
|
||||
|
||||
export type SelectTrigger<ED extends EntityDict, T extends keyof ED> = SelectTriggerBefore<ED, T> | SelectTriggerAfter<ED, T>;
|
||||
export type SelectTrigger<ED extends EntityDict, T extends keyof ED, Cxt extends Context<ED>> = SelectTriggerBefore<ED, T, Cxt> | SelectTriggerAfter<ED, T, Cxt>;
|
||||
|
||||
export type Trigger<ED extends EntityDict, T extends keyof ED> = CreateTrigger<ED, T> | UpdateTrigger<ED, T> | RemoveTrigger<ED, T> | SelectTrigger<ED, T>;
|
||||
export type Trigger<ED extends EntityDict, T extends keyof ED, Cxt extends Context<ED>> = CreateTrigger<ED, T, Cxt> | UpdateTrigger<ED, T, Cxt>
|
||||
| RemoveTrigger<ED, T, Cxt> | SelectTrigger<ED, T, Cxt>;
|
||||
|
||||
export interface TriggerEntityShape extends EntityShape {
|
||||
$$triggerData$$?: {
|
||||
|
|
@ -99,23 +100,23 @@ export interface TriggerEntityShape extends EntityShape {
|
|||
$$triggerTimestamp$$?: number;
|
||||
};
|
||||
|
||||
export abstract class Executor<ED extends EntityDict> {
|
||||
export abstract class Executor<ED extends EntityDict, Cxt extends Context<ED>> {
|
||||
static dataAttr: TriggerDataAttribute = '$$triggerData$$';
|
||||
static timestampAttr: TriggerTimestampAttribute = '$$triggerTimestamp$$';
|
||||
|
||||
abstract registerTrigger<T extends keyof ED>(trigger: Trigger<ED, T>): void;
|
||||
abstract registerTrigger<T extends keyof ED>(trigger: Trigger<ED, T, Cxt>): void;
|
||||
|
||||
abstract preOperation<T extends keyof ED>(
|
||||
entity: T,
|
||||
operation: ED[T]['Operation'],
|
||||
context: Context<ED>
|
||||
context: Cxt
|
||||
): Promise<void>;
|
||||
|
||||
abstract postOperation<T extends keyof ED>(
|
||||
entity: T,
|
||||
operation: ED[T]['Operation'],
|
||||
context: Context<ED>
|
||||
context: Cxt
|
||||
): Promise<void>;
|
||||
|
||||
abstract checkpoint(context: Context<ED>, timestamp: number): Promise<number>; // 将所有在timestamp之前存在不一致的数据进行恢复
|
||||
abstract checkpoint(context: Cxt, timestamp: number): Promise<number>; // 将所有在timestamp之前存在不一致的数据进行恢复
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,4 +11,5 @@ export * from './Logger';
|
|||
export * from './Polyfill';
|
||||
export * from './RowStore';
|
||||
export * from './Storage';
|
||||
export * from './Trigger';
|
||||
export * from './Trigger';
|
||||
export * from './Exception';
|
||||
Loading…
Reference in New Issue