Merge branch 'release'
This commit is contained in:
commit
d1829ce545
|
|
@ -5,7 +5,6 @@ import * as SubQuery from "../_SubQuery";
|
||||||
import { FormCreateData, FormUpdateData, DeduceAggregation, Operation as OakOperation, Selection as OakSelection, MakeAction as OakMakeAction, EntityShape, AggregationResult } from "../../types/Entity";
|
import { FormCreateData, FormUpdateData, DeduceAggregation, Operation as OakOperation, Selection as OakSelection, MakeAction as OakMakeAction, EntityShape, AggregationResult } from "../../types/Entity";
|
||||||
import { Action, ParticularAction, IState } from "./Action";
|
import { Action, ParticularAction, IState } from "./Action";
|
||||||
import * as ModiEntity from "../ModiEntity/Schema";
|
import * as ModiEntity from "../ModiEntity/Schema";
|
||||||
import * as OperEntity from "../OperEntity/Schema";
|
|
||||||
export declare type OpSchema = EntityShape & {
|
export declare type OpSchema = EntityShape & {
|
||||||
targetEntity: String<32>;
|
targetEntity: String<32>;
|
||||||
entity: String<32>;
|
entity: String<32>;
|
||||||
|
|
@ -28,8 +27,6 @@ export declare type Schema = EntityShape & {
|
||||||
iState?: IState | null;
|
iState?: IState | null;
|
||||||
modiEntity$modi?: Array<ModiEntity.Schema>;
|
modiEntity$modi?: Array<ModiEntity.Schema>;
|
||||||
modiEntity$modi$$aggr?: AggregationResult<ModiEntity.Schema>;
|
modiEntity$modi$$aggr?: AggregationResult<ModiEntity.Schema>;
|
||||||
operEntity$entity?: Array<OperEntity.Schema>;
|
|
||||||
operEntity$entity$$aggr?: AggregationResult<OperEntity.Schema>;
|
|
||||||
} & {
|
} & {
|
||||||
[A in ExpressionKey]?: any;
|
[A in ExpressionKey]?: any;
|
||||||
};
|
};
|
||||||
|
|
@ -69,12 +66,6 @@ export declare type Projection = {
|
||||||
modiEntity$modi$$aggr?: ModiEntity.Aggregation & {
|
modiEntity$modi$$aggr?: ModiEntity.Aggregation & {
|
||||||
$entity: "modiEntity";
|
$entity: "modiEntity";
|
||||||
};
|
};
|
||||||
operEntity$entity?: OperEntity.Selection & {
|
|
||||||
$entity: "operEntity";
|
|
||||||
};
|
|
||||||
operEntity$entity$$aggr?: OperEntity.Aggregation & {
|
|
||||||
$entity: "operEntity";
|
|
||||||
};
|
|
||||||
} & Partial<ExprOp<OpAttr | string>>;
|
} & Partial<ExprOp<OpAttr | string>>;
|
||||||
declare type ModiIdProjection = OneOf<{
|
declare type ModiIdProjection = OneOf<{
|
||||||
id: number;
|
id: number;
|
||||||
|
|
@ -114,7 +105,6 @@ export declare type CreateOperationData = FormCreateData<Omit<OpSchema, "entity"
|
||||||
[K: string]: any;
|
[K: string]: any;
|
||||||
}) & {
|
}) & {
|
||||||
modiEntity$modi?: OakOperation<"create", Omit<ModiEntity.CreateOperationData, "modi" | "modiId">[]> | Array<OakOperation<"create", Omit<ModiEntity.CreateOperationData, "modi" | "modiId">>>;
|
modiEntity$modi?: OakOperation<"create", Omit<ModiEntity.CreateOperationData, "modi" | "modiId">[]> | Array<OakOperation<"create", Omit<ModiEntity.CreateOperationData, "modi" | "modiId">>>;
|
||||||
operEntity$entity?: OakOperation<"create", Omit<OperEntity.CreateOperationData, "entity" | "entityId">[]> | Array<OakOperation<"create", Omit<OperEntity.CreateOperationData, "entity" | "entityId">>>;
|
|
||||||
};
|
};
|
||||||
export declare type CreateSingleOperation = OakOperation<"create", CreateOperationData>;
|
export declare type CreateSingleOperation = OakOperation<"create", CreateOperationData>;
|
||||||
export declare type CreateMultipleOperation = OakOperation<"create", Array<CreateOperationData>>;
|
export declare type CreateMultipleOperation = OakOperation<"create", Array<CreateOperationData>>;
|
||||||
|
|
@ -122,7 +112,6 @@ export declare type CreateOperation = CreateSingleOperation | CreateMultipleOper
|
||||||
export declare type UpdateOperationData = FormUpdateData<OpSchema> & {
|
export declare type UpdateOperationData = FormUpdateData<OpSchema> & {
|
||||||
[k: string]: any;
|
[k: string]: any;
|
||||||
modiEntity$modi?: OakOperation<"create", Omit<ModiEntity.CreateOperationData, "modi" | "modiId">[]> | Array<OakOperation<"create", Omit<ModiEntity.CreateOperationData, "modi" | "modiId">>>;
|
modiEntity$modi?: OakOperation<"create", Omit<ModiEntity.CreateOperationData, "modi" | "modiId">[]> | Array<OakOperation<"create", Omit<ModiEntity.CreateOperationData, "modi" | "modiId">>>;
|
||||||
operEntity$entity?: OakOperation<"create", Omit<OperEntity.CreateOperationData, "entity" | "entityId">[]> | Array<OakOperation<"create", Omit<OperEntity.CreateOperationData, "entity" | "entityId">>>;
|
|
||||||
};
|
};
|
||||||
export declare type UpdateOperation = OakOperation<"update" | ParticularAction | string, UpdateOperationData, Filter, Sorter>;
|
export declare type UpdateOperation = OakOperation<"update" | ParticularAction | string, UpdateOperationData, Filter, Sorter>;
|
||||||
export declare type RemoveOperationData = {};
|
export declare type RemoveOperationData = {};
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ export declare type OpSchema = EntityShape & {
|
||||||
filter?: Object | null;
|
filter?: Object | null;
|
||||||
extra?: Object | null;
|
extra?: Object | null;
|
||||||
operatorId?: ForeignKey<"user"> | null;
|
operatorId?: ForeignKey<"user"> | null;
|
||||||
|
targetEntity: String<32>;
|
||||||
};
|
};
|
||||||
export declare type OpAttr = keyof OpSchema;
|
export declare type OpAttr = keyof OpSchema;
|
||||||
export declare type Schema = EntityShape & {
|
export declare type Schema = EntityShape & {
|
||||||
|
|
@ -20,6 +21,7 @@ export declare type Schema = EntityShape & {
|
||||||
filter?: Object | null;
|
filter?: Object | null;
|
||||||
extra?: Object | null;
|
extra?: Object | null;
|
||||||
operatorId?: ForeignKey<"user"> | null;
|
operatorId?: ForeignKey<"user"> | null;
|
||||||
|
targetEntity: String<32>;
|
||||||
operator?: User.Schema | null;
|
operator?: User.Schema | null;
|
||||||
operEntity$oper?: Array<OperEntity.Schema>;
|
operEntity$oper?: Array<OperEntity.Schema>;
|
||||||
operEntity$oper$$aggr?: AggregationResult<OperEntity.Schema>;
|
operEntity$oper$$aggr?: AggregationResult<OperEntity.Schema>;
|
||||||
|
|
@ -37,6 +39,7 @@ declare type AttrFilter = {
|
||||||
extra: Object;
|
extra: Object;
|
||||||
operatorId: Q_StringValue | SubQuery.UserIdSubQuery;
|
operatorId: Q_StringValue | SubQuery.UserIdSubQuery;
|
||||||
operator: User.Filter;
|
operator: User.Filter;
|
||||||
|
targetEntity: Q_StringValue;
|
||||||
};
|
};
|
||||||
export declare type Filter = MakeFilter<AttrFilter & ExprOp<OpAttr | string>>;
|
export declare type Filter = MakeFilter<AttrFilter & ExprOp<OpAttr | string>>;
|
||||||
export declare type Projection = {
|
export declare type Projection = {
|
||||||
|
|
@ -52,6 +55,7 @@ export declare type Projection = {
|
||||||
extra?: number;
|
extra?: number;
|
||||||
operatorId?: number;
|
operatorId?: number;
|
||||||
operator?: User.Projection;
|
operator?: User.Projection;
|
||||||
|
targetEntity?: number;
|
||||||
operEntity$oper?: OperEntity.Selection & {
|
operEntity$oper?: OperEntity.Selection & {
|
||||||
$entity: "operEntity";
|
$entity: "operEntity";
|
||||||
};
|
};
|
||||||
|
|
@ -79,6 +83,8 @@ export declare type SortAttr = {
|
||||||
operatorId: number;
|
operatorId: number;
|
||||||
} | {
|
} | {
|
||||||
operator: User.SortAttr;
|
operator: User.SortAttr;
|
||||||
|
} | {
|
||||||
|
targetEntity: number;
|
||||||
} | {
|
} | {
|
||||||
[k: string]: any;
|
[k: string]: any;
|
||||||
} | OneOf<ExprOp<OpAttr | string>>;
|
} | OneOf<ExprOp<OpAttr | string>>;
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,12 @@ exports.desc = {
|
||||||
operatorId: {
|
operatorId: {
|
||||||
type: "ref",
|
type: "ref",
|
||||||
ref: "user"
|
ref: "user"
|
||||||
|
},
|
||||||
|
targetEntity: {
|
||||||
|
type: "varchar",
|
||||||
|
params: {
|
||||||
|
length: 32
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
actionType: "appendOnly",
|
actionType: "appendOnly",
|
||||||
|
|
|
||||||
|
|
@ -5,21 +5,19 @@ import * as SubQuery from "../_SubQuery";
|
||||||
import { FormCreateData, FormUpdateData, DeduceAggregation, Operation as OakOperation, Selection as OakSelection, MakeAction as OakMakeAction, EntityShape } from "../../types/Entity";
|
import { FormCreateData, FormUpdateData, DeduceAggregation, Operation as OakOperation, Selection as OakSelection, MakeAction as OakMakeAction, EntityShape } from "../../types/Entity";
|
||||||
import { AppendOnlyAction } from "../../actions/action";
|
import { AppendOnlyAction } from "../../actions/action";
|
||||||
import * as Oper from "../Oper/Schema";
|
import * as Oper from "../Oper/Schema";
|
||||||
import * as Modi from "../Modi/Schema";
|
|
||||||
import * as User from "../User/Schema";
|
import * as User from "../User/Schema";
|
||||||
import * as UserEntityGrant from "../UserEntityGrant/Schema";
|
import * as UserEntityGrant from "../UserEntityGrant/Schema";
|
||||||
export declare type OpSchema = EntityShape & {
|
export declare type OpSchema = EntityShape & {
|
||||||
operId: ForeignKey<"oper">;
|
operId: ForeignKey<"oper">;
|
||||||
entity: "modi" | "user" | "userEntityGrant" | string;
|
entity: "user" | "userEntityGrant" | string;
|
||||||
entityId: String<64>;
|
entityId: String<64>;
|
||||||
};
|
};
|
||||||
export declare type OpAttr = keyof OpSchema;
|
export declare type OpAttr = keyof OpSchema;
|
||||||
export declare type Schema = EntityShape & {
|
export declare type Schema = EntityShape & {
|
||||||
operId: ForeignKey<"oper">;
|
operId: ForeignKey<"oper">;
|
||||||
entity: "modi" | "user" | "userEntityGrant" | string;
|
entity: "user" | "userEntityGrant" | string;
|
||||||
entityId: String<64>;
|
entityId: String<64>;
|
||||||
oper: Oper.Schema;
|
oper: Oper.Schema;
|
||||||
modi?: Modi.Schema;
|
|
||||||
user?: User.Schema;
|
user?: User.Schema;
|
||||||
userEntityGrant?: UserEntityGrant.Schema;
|
userEntityGrant?: UserEntityGrant.Schema;
|
||||||
} & {
|
} & {
|
||||||
|
|
@ -34,11 +32,10 @@ declare type AttrFilter<E> = {
|
||||||
oper: Oper.Filter;
|
oper: Oper.Filter;
|
||||||
entity: E;
|
entity: E;
|
||||||
entityId: Q_StringValue;
|
entityId: Q_StringValue;
|
||||||
modi: Modi.Filter;
|
|
||||||
user: User.Filter;
|
user: User.Filter;
|
||||||
userEntityGrant: UserEntityGrant.Filter;
|
userEntityGrant: UserEntityGrant.Filter;
|
||||||
};
|
};
|
||||||
export declare type Filter<E = Q_EnumValue<"modi" | "user" | "userEntityGrant" | string>> = MakeFilter<AttrFilter<E> & ExprOp<OpAttr | string>>;
|
export declare type Filter<E = Q_EnumValue<"user" | "userEntityGrant" | string>> = MakeFilter<AttrFilter<E> & ExprOp<OpAttr | string>>;
|
||||||
export declare type Projection = {
|
export declare type Projection = {
|
||||||
"#id"?: NodeId;
|
"#id"?: NodeId;
|
||||||
[k: string]: any;
|
[k: string]: any;
|
||||||
|
|
@ -50,7 +47,6 @@ export declare type Projection = {
|
||||||
oper?: Oper.Projection;
|
oper?: Oper.Projection;
|
||||||
entity?: number;
|
entity?: number;
|
||||||
entityId?: number;
|
entityId?: number;
|
||||||
modi?: Modi.Projection;
|
|
||||||
user?: User.Projection;
|
user?: User.Projection;
|
||||||
userEntityGrant?: UserEntityGrant.Projection;
|
userEntityGrant?: UserEntityGrant.Projection;
|
||||||
} & Partial<ExprOp<OpAttr | string>>;
|
} & Partial<ExprOp<OpAttr | string>>;
|
||||||
|
|
@ -60,9 +56,6 @@ declare type OperEntityIdProjection = OneOf<{
|
||||||
declare type OperIdProjection = OneOf<{
|
declare type OperIdProjection = OneOf<{
|
||||||
operId: number;
|
operId: number;
|
||||||
}>;
|
}>;
|
||||||
declare type ModiIdProjection = OneOf<{
|
|
||||||
entityId: number;
|
|
||||||
}>;
|
|
||||||
declare type UserIdProjection = OneOf<{
|
declare type UserIdProjection = OneOf<{
|
||||||
entityId: number;
|
entityId: number;
|
||||||
}>;
|
}>;
|
||||||
|
|
@ -85,8 +78,6 @@ export declare type SortAttr = {
|
||||||
entity: number;
|
entity: number;
|
||||||
} | {
|
} | {
|
||||||
entityId: number;
|
entityId: number;
|
||||||
} | {
|
|
||||||
modi: Modi.SortAttr;
|
|
||||||
} | {
|
} | {
|
||||||
user: User.SortAttr;
|
user: User.SortAttr;
|
||||||
} | {
|
} | {
|
||||||
|
|
@ -108,17 +99,6 @@ export declare type CreateOperationData = FormCreateData<Omit<OpSchema, "entity"
|
||||||
} | {
|
} | {
|
||||||
operId: String<64>;
|
operId: String<64>;
|
||||||
})) & ({
|
})) & ({
|
||||||
entity?: never;
|
|
||||||
entityId?: never;
|
|
||||||
modi: Modi.CreateSingleOperation;
|
|
||||||
} | {
|
|
||||||
entity: "modi";
|
|
||||||
entityId: String<64>;
|
|
||||||
modi: Modi.UpdateOperation;
|
|
||||||
} | {
|
|
||||||
entity: "modi";
|
|
||||||
entityId: String<64>;
|
|
||||||
} | {
|
|
||||||
entity?: never;
|
entity?: never;
|
||||||
entityId?: never;
|
entityId?: never;
|
||||||
user: User.CreateSingleOperation;
|
user: User.CreateSingleOperation;
|
||||||
|
|
@ -155,10 +135,6 @@ export declare type UpdateOperationData = FormUpdateData<Omit<OpSchema, "entity"
|
||||||
oper?: never;
|
oper?: never;
|
||||||
operId?: String<64> | null;
|
operId?: String<64> | null;
|
||||||
})) & ({
|
})) & ({
|
||||||
modi?: Modi.CreateSingleOperation | Modi.UpdateOperation | Modi.RemoveOperation;
|
|
||||||
entityId?: never;
|
|
||||||
entity?: never;
|
|
||||||
} | {
|
|
||||||
user?: User.CreateSingleOperation | User.UpdateOperation | User.RemoveOperation;
|
user?: User.CreateSingleOperation | User.UpdateOperation | User.RemoveOperation;
|
||||||
entityId?: never;
|
entityId?: never;
|
||||||
entity?: never;
|
entity?: never;
|
||||||
|
|
@ -167,15 +143,13 @@ export declare type UpdateOperationData = FormUpdateData<Omit<OpSchema, "entity"
|
||||||
entityId?: never;
|
entityId?: never;
|
||||||
entity?: never;
|
entity?: never;
|
||||||
} | {
|
} | {
|
||||||
entity?: ("modi" | "user" | "userEntityGrant" | string) | null;
|
entity?: ("user" | "userEntityGrant" | string) | null;
|
||||||
entityId?: String<64> | null;
|
entityId?: String<64> | null;
|
||||||
}) & {
|
}) & {
|
||||||
[k: string]: any;
|
[k: string]: any;
|
||||||
};
|
};
|
||||||
export declare type UpdateOperation = OakOperation<"update" | string, UpdateOperationData, Filter, Sorter>;
|
export declare type UpdateOperation = OakOperation<"update" | string, UpdateOperationData, Filter, Sorter>;
|
||||||
export declare type RemoveOperationData = {} & ({
|
export declare type RemoveOperationData = {} & ({
|
||||||
modi?: Modi.UpdateOperation | Modi.RemoveOperation;
|
|
||||||
} | {
|
|
||||||
user?: User.UpdateOperation | User.RemoveOperation;
|
user?: User.UpdateOperation | User.RemoveOperation;
|
||||||
} | {
|
} | {
|
||||||
userEntityGrant?: UserEntityGrant.UpdateOperation | UserEntityGrant.RemoveOperation;
|
userEntityGrant?: UserEntityGrant.UpdateOperation | UserEntityGrant.RemoveOperation;
|
||||||
|
|
@ -185,7 +159,6 @@ export declare type RemoveOperationData = {} & ({
|
||||||
export declare type RemoveOperation = OakOperation<"remove", RemoveOperationData, Filter, Sorter>;
|
export declare type RemoveOperation = OakOperation<"remove", RemoveOperationData, Filter, Sorter>;
|
||||||
export declare type Operation = CreateOperation | UpdateOperation | RemoveOperation;
|
export declare type Operation = CreateOperation | UpdateOperation | RemoveOperation;
|
||||||
export declare type OperIdSubQuery = Selection<OperIdProjection>;
|
export declare type OperIdSubQuery = Selection<OperIdProjection>;
|
||||||
export declare type ModiIdSubQuery = Selection<ModiIdProjection>;
|
|
||||||
export declare type UserIdSubQuery = Selection<UserIdProjection>;
|
export declare type UserIdSubQuery = Selection<UserIdProjection>;
|
||||||
export declare type UserEntityGrantIdSubQuery = Selection<UserEntityGrantIdProjection>;
|
export declare type UserEntityGrantIdSubQuery = Selection<UserEntityGrantIdProjection>;
|
||||||
export declare type OperEntityIdSubQuery = Selection<OperEntityIdProjection>;
|
export declare type OperEntityIdSubQuery = Selection<OperEntityIdProjection>;
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ exports.desc = {
|
||||||
params: {
|
params: {
|
||||||
length: 32
|
length: 32
|
||||||
},
|
},
|
||||||
ref: ["modi", "user", "userEntityGrant"]
|
ref: ["user", "userEntityGrant"]
|
||||||
},
|
},
|
||||||
entityId: {
|
entityId: {
|
||||||
type: "varchar",
|
type: "varchar",
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,8 @@ import { FormCreateData, FormUpdateData, DeduceAggregation, Operation as OakOper
|
||||||
import { Action, ParticularAction, UserState } from "./Action";
|
import { Action, ParticularAction, UserState } from "./Action";
|
||||||
import { RelationAction } from "../../actions/action";
|
import { RelationAction } from "../../actions/action";
|
||||||
import * as Oper from "../Oper/Schema";
|
import * as Oper from "../Oper/Schema";
|
||||||
import * as OperEntity from "../OperEntity/Schema";
|
|
||||||
import * as ModiEntity from "../ModiEntity/Schema";
|
import * as ModiEntity from "../ModiEntity/Schema";
|
||||||
|
import * as OperEntity from "../OperEntity/Schema";
|
||||||
export declare type OpSchema = EntityShape & {
|
export declare type OpSchema = EntityShape & {
|
||||||
name?: String<16> | null;
|
name?: String<16> | null;
|
||||||
nickname?: String<64> | null;
|
nickname?: String<64> | null;
|
||||||
|
|
@ -27,10 +27,10 @@ export declare type Schema = EntityShape & {
|
||||||
oper$operator$$aggr?: AggregationResult<Oper.Schema>;
|
oper$operator$$aggr?: AggregationResult<Oper.Schema>;
|
||||||
user$ref?: Array<Schema>;
|
user$ref?: Array<Schema>;
|
||||||
user$ref$$aggr?: AggregationResult<Schema>;
|
user$ref$$aggr?: AggregationResult<Schema>;
|
||||||
operEntity$entity?: Array<OperEntity.Schema>;
|
|
||||||
operEntity$entity$$aggr?: AggregationResult<OperEntity.Schema>;
|
|
||||||
modiEntity$entity?: Array<ModiEntity.Schema>;
|
modiEntity$entity?: Array<ModiEntity.Schema>;
|
||||||
modiEntity$entity$$aggr?: AggregationResult<ModiEntity.Schema>;
|
modiEntity$entity$$aggr?: AggregationResult<ModiEntity.Schema>;
|
||||||
|
operEntity$entity?: Array<OperEntity.Schema>;
|
||||||
|
operEntity$entity$$aggr?: AggregationResult<OperEntity.Schema>;
|
||||||
} & {
|
} & {
|
||||||
[A in ExpressionKey]?: any;
|
[A in ExpressionKey]?: any;
|
||||||
};
|
};
|
||||||
|
|
@ -72,18 +72,18 @@ export declare type Projection = {
|
||||||
user$ref$$aggr?: Aggregation & {
|
user$ref$$aggr?: Aggregation & {
|
||||||
$entity: "user";
|
$entity: "user";
|
||||||
};
|
};
|
||||||
operEntity$entity?: OperEntity.Selection & {
|
|
||||||
$entity: "operEntity";
|
|
||||||
};
|
|
||||||
operEntity$entity$$aggr?: OperEntity.Aggregation & {
|
|
||||||
$entity: "operEntity";
|
|
||||||
};
|
|
||||||
modiEntity$entity?: ModiEntity.Selection & {
|
modiEntity$entity?: ModiEntity.Selection & {
|
||||||
$entity: "modiEntity";
|
$entity: "modiEntity";
|
||||||
};
|
};
|
||||||
modiEntity$entity$$aggr?: ModiEntity.Aggregation & {
|
modiEntity$entity$$aggr?: ModiEntity.Aggregation & {
|
||||||
$entity: "modiEntity";
|
$entity: "modiEntity";
|
||||||
};
|
};
|
||||||
|
operEntity$entity?: OperEntity.Selection & {
|
||||||
|
$entity: "operEntity";
|
||||||
|
};
|
||||||
|
operEntity$entity$$aggr?: OperEntity.Aggregation & {
|
||||||
|
$entity: "operEntity";
|
||||||
|
};
|
||||||
} & Partial<ExprOp<OpAttr | string>>;
|
} & Partial<ExprOp<OpAttr | string>>;
|
||||||
declare type UserIdProjection = OneOf<{
|
declare type UserIdProjection = OneOf<{
|
||||||
id: number;
|
id: number;
|
||||||
|
|
@ -131,8 +131,8 @@ export declare type CreateOperationData = FormCreateData<Omit<OpSchema, "refId">
|
||||||
})) & {
|
})) & {
|
||||||
oper$operator?: OakOperation<"create", Omit<Oper.CreateOperationData, "operator" | "operatorId">[]> | Array<OakOperation<"create", Omit<Oper.CreateOperationData, "operator" | "operatorId">>>;
|
oper$operator?: OakOperation<"create", Omit<Oper.CreateOperationData, "operator" | "operatorId">[]> | Array<OakOperation<"create", Omit<Oper.CreateOperationData, "operator" | "operatorId">>>;
|
||||||
user$ref?: OakOperation<UpdateOperation["action"], Omit<UpdateOperationData, "ref" | "refId">, Filter> | OakOperation<"create", Omit<CreateOperationData, "ref" | "refId">[]> | Array<OakOperation<"create", Omit<CreateOperationData, "ref" | "refId">> | OakOperation<UpdateOperation["action"], Omit<UpdateOperationData, "ref" | "refId">, Filter>>;
|
user$ref?: OakOperation<UpdateOperation["action"], Omit<UpdateOperationData, "ref" | "refId">, Filter> | OakOperation<"create", Omit<CreateOperationData, "ref" | "refId">[]> | Array<OakOperation<"create", Omit<CreateOperationData, "ref" | "refId">> | OakOperation<UpdateOperation["action"], Omit<UpdateOperationData, "ref" | "refId">, Filter>>;
|
||||||
operEntity$entity?: OakOperation<"create", Omit<OperEntity.CreateOperationData, "entity" | "entityId">[]> | Array<OakOperation<"create", Omit<OperEntity.CreateOperationData, "entity" | "entityId">>>;
|
|
||||||
modiEntity$entity?: OakOperation<"create", Omit<ModiEntity.CreateOperationData, "entity" | "entityId">[]> | Array<OakOperation<"create", Omit<ModiEntity.CreateOperationData, "entity" | "entityId">>>;
|
modiEntity$entity?: OakOperation<"create", Omit<ModiEntity.CreateOperationData, "entity" | "entityId">[]> | Array<OakOperation<"create", Omit<ModiEntity.CreateOperationData, "entity" | "entityId">>>;
|
||||||
|
operEntity$entity?: OakOperation<"create", Omit<OperEntity.CreateOperationData, "entity" | "entityId">[]> | Array<OakOperation<"create", Omit<OperEntity.CreateOperationData, "entity" | "entityId">>>;
|
||||||
};
|
};
|
||||||
export declare type CreateSingleOperation = OakOperation<"create", CreateOperationData>;
|
export declare type CreateSingleOperation = OakOperation<"create", CreateOperationData>;
|
||||||
export declare type CreateMultipleOperation = OakOperation<"create", Array<CreateOperationData>>;
|
export declare type CreateMultipleOperation = OakOperation<"create", Array<CreateOperationData>>;
|
||||||
|
|
@ -153,8 +153,8 @@ export declare type UpdateOperationData = FormUpdateData<Omit<OpSchema, "refId">
|
||||||
[k: string]: any;
|
[k: string]: any;
|
||||||
oper$operator?: OakOperation<"create", Omit<Oper.CreateOperationData, "operator" | "operatorId">[]> | Array<OakOperation<"create", Omit<Oper.CreateOperationData, "operator" | "operatorId">>>;
|
oper$operator?: OakOperation<"create", Omit<Oper.CreateOperationData, "operator" | "operatorId">[]> | Array<OakOperation<"create", Omit<Oper.CreateOperationData, "operator" | "operatorId">>>;
|
||||||
user$ref?: UpdateOperation | RemoveOperation | OakOperation<"create", Omit<CreateOperationData, "ref" | "refId">[]> | Array<OakOperation<"create", Omit<CreateOperationData, "ref" | "refId">> | UpdateOperation | RemoveOperation>;
|
user$ref?: UpdateOperation | RemoveOperation | OakOperation<"create", Omit<CreateOperationData, "ref" | "refId">[]> | Array<OakOperation<"create", Omit<CreateOperationData, "ref" | "refId">> | UpdateOperation | RemoveOperation>;
|
||||||
operEntity$entity?: OakOperation<"create", Omit<OperEntity.CreateOperationData, "entity" | "entityId">[]> | Array<OakOperation<"create", Omit<OperEntity.CreateOperationData, "entity" | "entityId">>>;
|
|
||||||
modiEntity$entity?: OakOperation<"create", Omit<ModiEntity.CreateOperationData, "entity" | "entityId">[]> | Array<OakOperation<"create", Omit<ModiEntity.CreateOperationData, "entity" | "entityId">>>;
|
modiEntity$entity?: OakOperation<"create", Omit<ModiEntity.CreateOperationData, "entity" | "entityId">[]> | Array<OakOperation<"create", Omit<ModiEntity.CreateOperationData, "entity" | "entityId">>>;
|
||||||
|
operEntity$entity?: OakOperation<"create", Omit<OperEntity.CreateOperationData, "entity" | "entityId">[]> | Array<OakOperation<"create", Omit<OperEntity.CreateOperationData, "entity" | "entityId">>>;
|
||||||
};
|
};
|
||||||
export declare type UpdateOperation = OakOperation<"update" | ParticularAction | RelationAction | string, UpdateOperationData, Filter, Sorter>;
|
export declare type UpdateOperation = OakOperation<"update" | ParticularAction | RelationAction | string, UpdateOperationData, Filter, Sorter>;
|
||||||
export declare type RemoveOperationData = {} & (({
|
export declare type RemoveOperationData = {} & (({
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,8 @@ import { OneOf } from "../../types/Polyfill";
|
||||||
import * as SubQuery from "../_SubQuery";
|
import * as SubQuery from "../_SubQuery";
|
||||||
import { FormCreateData, FormUpdateData, DeduceAggregation, Operation as OakOperation, Selection as OakSelection, MakeAction as OakMakeAction, EntityShape, AggregationResult } from "../../types/Entity";
|
import { FormCreateData, FormUpdateData, DeduceAggregation, Operation as OakOperation, Selection as OakSelection, MakeAction as OakMakeAction, EntityShape, AggregationResult } from "../../types/Entity";
|
||||||
import { GenericAction } from "../../actions/action";
|
import { GenericAction } from "../../actions/action";
|
||||||
import * as OperEntity from "../OperEntity/Schema";
|
|
||||||
import * as ModiEntity from "../ModiEntity/Schema";
|
import * as ModiEntity from "../ModiEntity/Schema";
|
||||||
|
import * as OperEntity from "../OperEntity/Schema";
|
||||||
export declare type OpSchema = EntityShape & {
|
export declare type OpSchema = EntityShape & {
|
||||||
entity: String<32>;
|
entity: String<32>;
|
||||||
entityId: String<64>;
|
entityId: String<64>;
|
||||||
|
|
@ -16,10 +16,10 @@ export declare type Schema = EntityShape & {
|
||||||
entity: String<32>;
|
entity: String<32>;
|
||||||
entityId: String<64>;
|
entityId: String<64>;
|
||||||
relation: String<32>;
|
relation: String<32>;
|
||||||
operEntity$entity?: Array<OperEntity.Schema>;
|
|
||||||
operEntity$entity$$aggr?: AggregationResult<OperEntity.Schema>;
|
|
||||||
modiEntity$entity?: Array<ModiEntity.Schema>;
|
modiEntity$entity?: Array<ModiEntity.Schema>;
|
||||||
modiEntity$entity$$aggr?: AggregationResult<ModiEntity.Schema>;
|
modiEntity$entity$$aggr?: AggregationResult<ModiEntity.Schema>;
|
||||||
|
operEntity$entity?: Array<OperEntity.Schema>;
|
||||||
|
operEntity$entity$$aggr?: AggregationResult<OperEntity.Schema>;
|
||||||
} & {
|
} & {
|
||||||
[A in ExpressionKey]?: any;
|
[A in ExpressionKey]?: any;
|
||||||
};
|
};
|
||||||
|
|
@ -43,18 +43,18 @@ export declare type Projection = {
|
||||||
entity?: number;
|
entity?: number;
|
||||||
entityId?: number;
|
entityId?: number;
|
||||||
relation?: number;
|
relation?: number;
|
||||||
operEntity$entity?: OperEntity.Selection & {
|
|
||||||
$entity: "operEntity";
|
|
||||||
};
|
|
||||||
operEntity$entity$$aggr?: OperEntity.Aggregation & {
|
|
||||||
$entity: "operEntity";
|
|
||||||
};
|
|
||||||
modiEntity$entity?: ModiEntity.Selection & {
|
modiEntity$entity?: ModiEntity.Selection & {
|
||||||
$entity: "modiEntity";
|
$entity: "modiEntity";
|
||||||
};
|
};
|
||||||
modiEntity$entity$$aggr?: ModiEntity.Aggregation & {
|
modiEntity$entity$$aggr?: ModiEntity.Aggregation & {
|
||||||
$entity: "modiEntity";
|
$entity: "modiEntity";
|
||||||
};
|
};
|
||||||
|
operEntity$entity?: OperEntity.Selection & {
|
||||||
|
$entity: "operEntity";
|
||||||
|
};
|
||||||
|
operEntity$entity$$aggr?: OperEntity.Aggregation & {
|
||||||
|
$entity: "operEntity";
|
||||||
|
};
|
||||||
} & Partial<ExprOp<OpAttr | string>>;
|
} & Partial<ExprOp<OpAttr | string>>;
|
||||||
declare type UserEntityGrantIdProjection = OneOf<{
|
declare type UserEntityGrantIdProjection = OneOf<{
|
||||||
id: number;
|
id: number;
|
||||||
|
|
@ -89,16 +89,16 @@ export declare type CreateOperationData = FormCreateData<Omit<OpSchema, "entity"
|
||||||
entityId?: string;
|
entityId?: string;
|
||||||
[K: string]: any;
|
[K: string]: any;
|
||||||
}) & {
|
}) & {
|
||||||
operEntity$entity?: OakOperation<"create", Omit<OperEntity.CreateOperationData, "entity" | "entityId">[]> | Array<OakOperation<"create", Omit<OperEntity.CreateOperationData, "entity" | "entityId">>>;
|
|
||||||
modiEntity$entity?: OakOperation<"create", Omit<ModiEntity.CreateOperationData, "entity" | "entityId">[]> | Array<OakOperation<"create", Omit<ModiEntity.CreateOperationData, "entity" | "entityId">>>;
|
modiEntity$entity?: OakOperation<"create", Omit<ModiEntity.CreateOperationData, "entity" | "entityId">[]> | Array<OakOperation<"create", Omit<ModiEntity.CreateOperationData, "entity" | "entityId">>>;
|
||||||
|
operEntity$entity?: OakOperation<"create", Omit<OperEntity.CreateOperationData, "entity" | "entityId">[]> | Array<OakOperation<"create", Omit<OperEntity.CreateOperationData, "entity" | "entityId">>>;
|
||||||
};
|
};
|
||||||
export declare type CreateSingleOperation = OakOperation<"create", CreateOperationData>;
|
export declare type CreateSingleOperation = OakOperation<"create", CreateOperationData>;
|
||||||
export declare type CreateMultipleOperation = OakOperation<"create", Array<CreateOperationData>>;
|
export declare type CreateMultipleOperation = OakOperation<"create", Array<CreateOperationData>>;
|
||||||
export declare type CreateOperation = CreateSingleOperation | CreateMultipleOperation;
|
export declare type CreateOperation = CreateSingleOperation | CreateMultipleOperation;
|
||||||
export declare type UpdateOperationData = FormUpdateData<OpSchema> & {
|
export declare type UpdateOperationData = FormUpdateData<OpSchema> & {
|
||||||
[k: string]: any;
|
[k: string]: any;
|
||||||
operEntity$entity?: OakOperation<"create", Omit<OperEntity.CreateOperationData, "entity" | "entityId">[]> | Array<OakOperation<"create", Omit<OperEntity.CreateOperationData, "entity" | "entityId">>>;
|
|
||||||
modiEntity$entity?: OakOperation<"create", Omit<ModiEntity.CreateOperationData, "entity" | "entityId">[]> | Array<OakOperation<"create", Omit<ModiEntity.CreateOperationData, "entity" | "entityId">>>;
|
modiEntity$entity?: OakOperation<"create", Omit<ModiEntity.CreateOperationData, "entity" | "entityId">[]> | Array<OakOperation<"create", Omit<ModiEntity.CreateOperationData, "entity" | "entityId">>>;
|
||||||
|
operEntity$entity?: OakOperation<"create", Omit<OperEntity.CreateOperationData, "entity" | "entityId">[]> | Array<OakOperation<"create", Omit<OperEntity.CreateOperationData, "entity" | "entityId">>>;
|
||||||
};
|
};
|
||||||
export declare type UpdateOperation = OakOperation<"update" | string, UpdateOperationData, Filter, Sorter>;
|
export declare type UpdateOperation = OakOperation<"update" | string, UpdateOperationData, Filter, Sorter>;
|
||||||
export declare type RemoveOperationData = {};
|
export declare type RemoveOperationData = {};
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ export declare const ENTITY_PATH_IN_OAK_DOMAIN: () => string;
|
||||||
export declare const TYPE_PATH_IN_OAK_DOMAIN: (level?: number) => string;
|
export declare const TYPE_PATH_IN_OAK_DOMAIN: (level?: number) => string;
|
||||||
export declare const ACTION_CONSTANT_IN_OAK_DOMAIN: (level?: number) => string;
|
export declare const ACTION_CONSTANT_IN_OAK_DOMAIN: (level?: number) => string;
|
||||||
export declare const RESERVED_ENTITIES: string[];
|
export declare const RESERVED_ENTITIES: string[];
|
||||||
|
export declare const ENTITY_NAME_MAX_LENGTH = 32;
|
||||||
export declare const STRING_LITERAL_MAX_LENGTH = 24;
|
export declare const STRING_LITERAL_MAX_LENGTH = 24;
|
||||||
export declare const NUMERICAL_LITERL_DEFAULT_PRECISION = 8;
|
export declare const NUMERICAL_LITERL_DEFAULT_PRECISION = 8;
|
||||||
export declare const NUMERICAL_LITERL_DEFAULT_SCALE = 2;
|
export declare const NUMERICAL_LITERL_DEFAULT_SCALE = 2;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
exports.INT_LITERL_DEFAULT_WIDTH = exports.NUMERICAL_LITERL_DEFAULT_SCALE = exports.NUMERICAL_LITERL_DEFAULT_PRECISION = exports.STRING_LITERAL_MAX_LENGTH = exports.RESERVED_ENTITIES = exports.ACTION_CONSTANT_IN_OAK_DOMAIN = exports.TYPE_PATH_IN_OAK_DOMAIN = exports.ENTITY_PATH_IN_OAK_DOMAIN = exports.ENTITY_PATH_IN_OAK_GENERAL_BUSINESS = exports.LIB_PATH = exports.LIB_OAK_DOMAIN = void 0;
|
exports.INT_LITERL_DEFAULT_WIDTH = exports.NUMERICAL_LITERL_DEFAULT_SCALE = exports.NUMERICAL_LITERL_DEFAULT_PRECISION = exports.STRING_LITERAL_MAX_LENGTH = exports.ENTITY_NAME_MAX_LENGTH = exports.RESERVED_ENTITIES = exports.ACTION_CONSTANT_IN_OAK_DOMAIN = exports.TYPE_PATH_IN_OAK_DOMAIN = exports.ENTITY_PATH_IN_OAK_DOMAIN = exports.ENTITY_PATH_IN_OAK_GENERAL_BUSINESS = exports.LIB_PATH = exports.LIB_OAK_DOMAIN = void 0;
|
||||||
exports.LIB_OAK_DOMAIN = 'oak-domain';
|
exports.LIB_OAK_DOMAIN = 'oak-domain';
|
||||||
var LIB_OAK_GENERAL_BUSINESS = 'oak-general-business';
|
var LIB_OAK_GENERAL_BUSINESS = 'oak-general-business';
|
||||||
var LIB_PATH = function () { return 'lib'; };
|
var LIB_PATH = function () { return 'lib'; };
|
||||||
|
|
@ -33,6 +33,7 @@ exports.ACTION_CONSTANT_IN_OAK_DOMAIN = ACTION_CONSTANT_IN_OAK_DOMAIN;
|
||||||
// export const OUTPUT_PATH = 'app-domain/entities';
|
// export const OUTPUT_PATH = 'app-domain/entities';
|
||||||
exports.RESERVED_ENTITIES = ['Schema', 'Filter', 'Query', 'SubQuery', 'Entity', 'Selection', 'Operation', 'File', 'Common',
|
exports.RESERVED_ENTITIES = ['Schema', 'Filter', 'Query', 'SubQuery', 'Entity', 'Selection', 'Operation', 'File', 'Common',
|
||||||
'Locale', 'Projection', 'Data'];
|
'Locale', 'Projection', 'Data'];
|
||||||
|
exports.ENTITY_NAME_MAX_LENGTH = 32;
|
||||||
exports.STRING_LITERAL_MAX_LENGTH = 24;
|
exports.STRING_LITERAL_MAX_LENGTH = 24;
|
||||||
exports.NUMERICAL_LITERL_DEFAULT_PRECISION = 8;
|
exports.NUMERICAL_LITERL_DEFAULT_PRECISION = 8;
|
||||||
exports.NUMERICAL_LITERL_DEFAULT_SCALE = 2;
|
exports.NUMERICAL_LITERL_DEFAULT_SCALE = 2;
|
||||||
|
|
|
||||||
|
|
@ -344,6 +344,18 @@ function getStringEnumValues(filename, program, obj, node) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
function checkNameLegal(filename, attrName, upperCase) {
|
||||||
|
(0, assert_1.default)(attrName.length <= env_1.ENTITY_NAME_MAX_LENGTH, "\u6587\u4EF6\u300C".concat(filename, "\u300D\uFF1A\u300C").concat(attrName, "\u300D\u7684\u540D\u79F0\u5B9A\u4E49\u8FC7\u957F\uFF0C\u4E0D\u80FD\u8D85\u8FC7\u300C").concat(env_1.ENTITY_NAME_MAX_LENGTH, "\u300D\u957F\u5EA6"));
|
||||||
|
if (upperCase) {
|
||||||
|
(0, assert_1.default)(/[A-Z][a-z|A-Z|0-9]+/i.test(attrName), "\u6587\u4EF6\u300C".concat(filename, "\u300D\uFF1A\u300C").concat(attrName, "\u300D\u7684\u540D\u79F0\u5FC5\u987B\u4EE5\u5927\u5199\u5B57\u6BCD\u5F00\u59CB\uFF0C\u4E14\u53EA\u80FD\u5305\u542B\u5B57\u6BCD\u548C\u6570\u5B57"));
|
||||||
|
}
|
||||||
|
else if (upperCase === false) {
|
||||||
|
(0, assert_1.default)(/[a-z][a-z|A-Z|0-9]+/i.test(attrName), "\u6587\u4EF6\u300C".concat(filename, "\u300D\uFF1A\u300C").concat(attrName, "\u300D\u7684\u540D\u79F0\u5FC5\u987B\u4EE5\u5C0F\u5199\u5B57\u6BCD\u5F00\u59CB\uFF0C\u4E14\u53EA\u80FD\u5305\u542B\u5B57\u6BCD\u548C\u6570\u5B57"));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
(0, assert_1.default)(/[a-z|A-Z][a-z|A-Z|0-9]+/i.test(attrName), "\u6587\u4EF6\u300C".concat(filename, "\u300D\uFF1A\u300C").concat(attrName, "\u300D\u7684\u540D\u79F0\u5FC5\u987B\u4EE5\u5B57\u6BCD\u5F00\u59CB\uFF0C\u4E14\u53EA\u80FD\u5305\u542B\u5B57\u6BCD\u548C\u6570\u5B57"));
|
||||||
|
}
|
||||||
|
}
|
||||||
function analyzeEntity(filename, path, program, relativePath) {
|
function analyzeEntity(filename, path, program, relativePath) {
|
||||||
var _a;
|
var _a;
|
||||||
var fullPath = "".concat(path, "/").concat(filename);
|
var fullPath = "".concat(path, "/").concat(filename);
|
||||||
|
|
@ -355,6 +367,7 @@ function analyzeEntity(filename, path, program, relativePath) {
|
||||||
// removeFromRelationShip(moduleName);
|
// removeFromRelationShip(moduleName);
|
||||||
console.warn("\u51FA\u73B0\u4E86\u540C\u540D\u7684Entity\u5B9A\u4E49\u300C".concat(moduleName, "\u300D\uFF0C\u5C06\u4F7F\u7528").concat(fullPath, "\u53D6\u4EE3\u6389\u9ED8\u8BA4\u5BF9\u8C61\uFF0C\u8BF7\u68C0\u67E5\u65B0\u7684\u5BF9\u8C61\u7ED3\u6784\u53CA\u76F8\u5173\u5E38\u91CF\u5B9A\u4E49\u4E0E\u539F\u6709\u7684\u517C\u5BB9\uFF0C\u5426\u5219\u539F\u6709\u5BF9\u8C61\u7684\u76F8\u5173\u903B\u8F91\u4F1A\u51FA\u73B0\u4E0D\u53EF\u77E5\u5F02\u5E38"));
|
console.warn("\u51FA\u73B0\u4E86\u540C\u540D\u7684Entity\u5B9A\u4E49\u300C".concat(moduleName, "\u300D\uFF0C\u5C06\u4F7F\u7528").concat(fullPath, "\u53D6\u4EE3\u6389\u9ED8\u8BA4\u5BF9\u8C61\uFF0C\u8BF7\u68C0\u67E5\u65B0\u7684\u5BF9\u8C61\u7ED3\u6784\u53CA\u76F8\u5173\u5E38\u91CF\u5B9A\u4E49\u4E0E\u539F\u6709\u7684\u517C\u5BB9\uFF0C\u5426\u5219\u539F\u6709\u5BF9\u8C61\u7684\u76F8\u5173\u903B\u8F91\u4F1A\u51FA\u73B0\u4E0D\u53EF\u77E5\u5F02\u5E38"));
|
||||||
}
|
}
|
||||||
|
checkNameLegal(filename, moduleName, true);
|
||||||
var referencedSchemas = [];
|
var referencedSchemas = [];
|
||||||
var schemaAttrs = [];
|
var schemaAttrs = [];
|
||||||
var hasFulltextIndex = false;
|
var hasFulltextIndex = false;
|
||||||
|
|
@ -406,6 +419,7 @@ function analyzeEntity(filename, path, program, relativePath) {
|
||||||
var _a, _b;
|
var _a, _b;
|
||||||
var _c = attrNode, type = _c.type, name = _c.name, questionToken = _c.questionToken;
|
var _c = attrNode, type = _c.type, name = _c.name, questionToken = _c.questionToken;
|
||||||
var attrName = name.text;
|
var attrName = name.text;
|
||||||
|
checkNameLegal(filename, attrName, false);
|
||||||
if (ts.isTypeReferenceNode(type)
|
if (ts.isTypeReferenceNode(type)
|
||||||
&& ts.isIdentifier(type.typeName)) {
|
&& ts.isIdentifier(type.typeName)) {
|
||||||
if ((referencedSchemas.includes(type.typeName.text) || type.typeName.text === 'Schema')) {
|
if ((referencedSchemas.includes(type.typeName.text) || type.typeName.text === 'Schema')) {
|
||||||
|
|
@ -516,27 +530,27 @@ function analyzeEntity(filename, path, program, relativePath) {
|
||||||
_a[moduleName] = 1,
|
_a[moduleName] = 1,
|
||||||
_a));
|
_a));
|
||||||
}
|
}
|
||||||
|
else if (hasEntityAttr_1 || hasEntityIdAttr_1) {
|
||||||
|
throw new Error("\u6587\u4EF6\u300C".concat(filename, "\u300D\uFF1A\u5C5E\u6027 \u5B9A\u4E49\u4E2D\u53EA\u5305\u542B").concat(hasEntityAttr_1 ? 'entity' : 'entityId', "\uFF0C\u4E0D\u7B26\u5408\u5B9A\u4E49\u89C4\u8303\u3002entity/entityId\u5FC5\u987B\u8054\u5408\u51FA\u73B0\uFF0C\u4EE3\u8868\u4E0D\u5B9A\u5BF9\u8C61\u7684\u53CD\u5411\u6307\u9488"));
|
||||||
|
}
|
||||||
beforeSchema = false;
|
beforeSchema = false;
|
||||||
// 对于不是Oper的对象,全部建立和OperEntity的反指关系
|
// 对于不是Modi和Oper的对象,全部建立和ModiEntity的反指关系
|
||||||
if (!['Oper', 'OperEntity', 'ModiEntity'].includes(moduleName)) {
|
if (!['Modi', 'Oper', 'OperEntity', 'ModiEntity'].includes(moduleName) && !toModi) {
|
||||||
if (ReversePointerRelations['OperEntity'] && !ReversePointerRelations['OperEntity'].includes(moduleName)) {
|
|
||||||
ReversePointerRelations['OperEntity'].push(moduleName);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
(0, lodash_1.assign)(ReversePointerRelations, (_b = {},
|
|
||||||
_b['OperEntity'] = [moduleName],
|
|
||||||
_b));
|
|
||||||
}
|
|
||||||
// 对于不是Modi的对象,全部建立和ModiEntity的反指关系
|
|
||||||
if (!['Modi'].includes(moduleName) && !toModi) {
|
|
||||||
if (ReversePointerRelations['ModiEntity'] && !ReversePointerRelations['ModiEntity'].includes(moduleName)) {
|
if (ReversePointerRelations['ModiEntity'] && !ReversePointerRelations['ModiEntity'].includes(moduleName)) {
|
||||||
ReversePointerRelations['ModiEntity'].push(moduleName);
|
ReversePointerRelations['ModiEntity'].push(moduleName);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
(0, lodash_1.assign)(ReversePointerRelations, (_c = {},
|
(0, lodash_1.assign)(ReversePointerRelations, (_b = {},
|
||||||
_c['ModiEntity'] = [moduleName],
|
_b['ModiEntity'] = [moduleName],
|
||||||
_c));
|
_b));
|
||||||
}
|
}
|
||||||
|
if (ReversePointerRelations['OperEntity'] && !ReversePointerRelations['OperEntity'].includes(moduleName)) {
|
||||||
|
ReversePointerRelations['OperEntity'].push(moduleName);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
(0, lodash_1.assign)(ReversePointerRelations, (_c = {},
|
||||||
|
_c['OperEntity'] = [moduleName],
|
||||||
|
_c));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,4 +7,5 @@ export interface Schema extends EntityShape {
|
||||||
filter?: Object;
|
filter?: Object;
|
||||||
extra?: Object;
|
extra?: Object;
|
||||||
operator?: User;
|
operator?: User;
|
||||||
|
targetEntity: String<32>;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ var locale = {
|
||||||
filter: '选择条件',
|
filter: '选择条件',
|
||||||
extra: '其它',
|
extra: '其它',
|
||||||
operator: '操作者',
|
operator: '操作者',
|
||||||
|
targetEntity: '关联对象',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
import { EntityDict, RowStore, OperateOption, OperationResult, SelectOption, Context, TxnOption, OpRecord, AggregationResult } from "../types";
|
import { EntityDict, RowStore, OperateOption, OperationResult, SelectOption, Context, TxnOption, OpRecord, AggregationResult } from "../types";
|
||||||
import { IncomingHttpHeaders } from "http";
|
import { IncomingHttpHeaders } from "http";
|
||||||
export declare abstract class AsyncContext<ED extends EntityDict> implements Context {
|
export declare abstract class AsyncContext<ED extends EntityDict> implements Context {
|
||||||
private rowStore;
|
rowStore: AsyncRowStore<ED, this>;
|
||||||
private uuid?;
|
private uuid?;
|
||||||
opRecords: OpRecord<ED>[];
|
opRecords: OpRecord<ED>[];
|
||||||
private scene?;
|
private scene?;
|
||||||
|
|
@ -12,6 +12,10 @@ export declare abstract class AsyncContext<ED extends EntityDict> implements Con
|
||||||
commit: Array<() => Promise<void>>;
|
commit: Array<() => Promise<void>>;
|
||||||
rollback: Array<() => Promise<void>>;
|
rollback: Array<() => Promise<void>>;
|
||||||
};
|
};
|
||||||
|
/**
|
||||||
|
* 在返回结果前调用,对数据行进行一些预处理,比如将一些敏感的列隐藏
|
||||||
|
*/
|
||||||
|
abstract refineOpRecords(): Promise<void>;
|
||||||
constructor(store: AsyncRowStore<ED, AsyncContext<ED>>, headers?: IncomingHttpHeaders);
|
constructor(store: AsyncRowStore<ED, AsyncContext<ED>>, headers?: IncomingHttpHeaders);
|
||||||
setHeaders(headers: IncomingHttpHeaders): void;
|
setHeaders(headers: IncomingHttpHeaders): void;
|
||||||
getHeader(key: string): string | string[] | undefined;
|
getHeader(key: string): string | string[] | undefined;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { EntityDict, OperateOption, SelectOption, OperationResult, AggregationResult } from "../types/Entity";
|
import { EntityDict, OperateOption, SelectOption, OperationResult, AggregationResult } from "../types/Entity";
|
||||||
import { EntityDict as BaseEntityDict } from '../base-app-domain';
|
import { EntityDict as BaseEntityDict } from '../base-app-domain';
|
||||||
import { RowStore } from '../types/RowStore';
|
import { OperationRewriter, RowStore, SelectionRewriter } from '../types/RowStore';
|
||||||
import { StorageSchema } from '../types/Storage';
|
import { StorageSchema } from '../types/Storage';
|
||||||
import { SyncContext } from "./SyncRowStore";
|
import { SyncContext } from "./SyncRowStore";
|
||||||
import { AsyncContext } from "./AsyncRowStore";
|
import { AsyncContext } from "./AsyncRowStore";
|
||||||
|
|
@ -9,6 +9,12 @@ export declare abstract class CascadeStore<ED extends EntityDict & BaseEntityDic
|
||||||
constructor(storageSchema: StorageSchema<ED>);
|
constructor(storageSchema: StorageSchema<ED>);
|
||||||
protected abstract supportManyToOneJoin(): boolean;
|
protected abstract supportManyToOneJoin(): boolean;
|
||||||
protected abstract supportMultipleCreate(): boolean;
|
protected abstract supportMultipleCreate(): boolean;
|
||||||
|
private selectionRewriters;
|
||||||
|
private operationRewriters;
|
||||||
|
private reinforceSelection;
|
||||||
|
private reinforceOperation;
|
||||||
|
registerOperationRewriter(rewriter: OperationRewriter<ED>): void;
|
||||||
|
registerSelectionRewriter(rewriter: SelectionRewriter<ED>): void;
|
||||||
protected abstract selectAbjointRow<T extends keyof ED, OP extends SelectOption, Cxt extends SyncContext<ED>>(entity: T, selection: ED[T]['Selection'], context: Cxt, option: OP): Partial<ED[T]['Schema']>[];
|
protected abstract selectAbjointRow<T extends keyof ED, OP extends SelectOption, Cxt extends SyncContext<ED>>(entity: T, selection: ED[T]['Selection'], context: Cxt, option: OP): Partial<ED[T]['Schema']>[];
|
||||||
protected abstract updateAbjointRow<T extends keyof ED, OP extends OperateOption, Cxt extends SyncContext<ED>>(entity: T, operation: ED[T]['Operation'], context: Cxt, option: OP): number;
|
protected abstract updateAbjointRow<T extends keyof ED, OP extends OperateOption, Cxt extends SyncContext<ED>>(entity: T, operation: ED[T]['Operation'], context: Cxt, option: OP): number;
|
||||||
protected abstract selectAbjointRowAsync<T extends keyof ED, OP extends SelectOption, Cxt extends AsyncContext<ED>>(entity: T, selection: ED[T]['Selection'], context: Cxt, option: OP): Promise<Partial<ED[T]['Schema']>[]>;
|
protected abstract selectAbjointRowAsync<T extends keyof ED, OP extends SelectOption, Cxt extends AsyncContext<ED>>(entity: T, selection: ED[T]['Selection'], context: Cxt, option: OP): Promise<Partial<ED[T]['Schema']>[]>;
|
||||||
|
|
|
||||||
|
|
@ -11,13 +11,251 @@ var types_1 = require("../types");
|
||||||
var lodash_1 = require("../utils/lodash");
|
var lodash_1 = require("../utils/lodash");
|
||||||
var filter_2 = require("./filter");
|
var filter_2 = require("./filter");
|
||||||
var uuid_1 = require("../utils/uuid");
|
var uuid_1 = require("../utils/uuid");
|
||||||
var selection_1 = require("./selection");
|
|
||||||
/**这个用来处理级联的select和update,对不同能力的 */
|
/**这个用来处理级联的select和update,对不同能力的 */
|
||||||
var CascadeStore = /** @class */ (function (_super) {
|
var CascadeStore = /** @class */ (function (_super) {
|
||||||
tslib_1.__extends(CascadeStore, _super);
|
tslib_1.__extends(CascadeStore, _super);
|
||||||
function CascadeStore(storageSchema) {
|
function CascadeStore(storageSchema) {
|
||||||
return _super.call(this, storageSchema) || this;
|
var _this = _super.call(this, storageSchema) || this;
|
||||||
|
_this.selectionRewriters = [];
|
||||||
|
_this.operationRewriters = [];
|
||||||
|
return _this;
|
||||||
}
|
}
|
||||||
|
CascadeStore.prototype.reinforceSelection = function (entity, selection) {
|
||||||
|
var _this = this;
|
||||||
|
var filter = selection.filter, data = selection.data, sorter = selection.sorter;
|
||||||
|
var checkNode = function (projectionNode, attrs) {
|
||||||
|
attrs.forEach(function (attr) {
|
||||||
|
var _a;
|
||||||
|
if (!projectionNode.hasOwnProperty(attr)) {
|
||||||
|
Object.assign(projectionNode, (_a = {},
|
||||||
|
_a[attr] = 1,
|
||||||
|
_a));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
var relevantIds = [];
|
||||||
|
if (filter) {
|
||||||
|
var toBeAssignNode_1 = {}; // 用来记录在表达式中涉及到的结点
|
||||||
|
// filter当中所关联到的属性必须在projection中
|
||||||
|
var filterNodeDict_1 = {};
|
||||||
|
var checkFilterNode_1 = function (entity2, filterNode, projectionNode) {
|
||||||
|
var _a, e_1, _b, _c, _d, _e, _f;
|
||||||
|
var necessaryAttrs = ['id'];
|
||||||
|
for (var attr in filterNode) {
|
||||||
|
if (attr === '#id') {
|
||||||
|
(0, assert_1.default)(!filterNodeDict_1[filterNode[attr]], "projection\u4E2D\u7ED3\u70B9\u7684id\u6709\u91CD\u590D, ".concat(filterNode[attr]));
|
||||||
|
Object.assign(filterNodeDict_1, (_a = {},
|
||||||
|
_a[filterNode[attr]] = projectionNode,
|
||||||
|
_a));
|
||||||
|
if (toBeAssignNode_1[filterNode[attr]]) {
|
||||||
|
checkNode(projectionNode, toBeAssignNode_1[filterNode[attr]]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (['$and', '$or'].includes(attr)) {
|
||||||
|
try {
|
||||||
|
for (var _g = (e_1 = void 0, tslib_1.__values(filterNode[attr])), _h = _g.next(); !_h.done; _h = _g.next()) {
|
||||||
|
var node = _h.value;
|
||||||
|
checkFilterNode_1(entity2, node, projectionNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
||||||
|
finally {
|
||||||
|
try {
|
||||||
|
if (_h && !_h.done && (_b = _g.return)) _b.call(_g);
|
||||||
|
}
|
||||||
|
finally { if (e_1) throw e_1.error; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (attr === '$not') {
|
||||||
|
checkFilterNode_1(entity2, filterNode[attr], projectionNode);
|
||||||
|
}
|
||||||
|
else if (attr === '$text') {
|
||||||
|
// 全文检索首先要有fulltext索引,其次要把fulltext的相关属性加到projection里
|
||||||
|
var indexes = _this.getSchema()[entity2].indexes;
|
||||||
|
var fulltextIndex = indexes.find(function (ele) { return ele.config && ele.config.type === 'fulltext'; });
|
||||||
|
var attributes = fulltextIndex.attributes;
|
||||||
|
necessaryAttrs.push.apply(necessaryAttrs, tslib_1.__spreadArray([], tslib_1.__read((attributes.map(function (ele) { return ele.name; }))), false));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (attr.toLowerCase().startsWith(types_1.EXPRESSION_PREFIX)) {
|
||||||
|
var exprResult = (0, types_1.getAttrRefInExpression)(filterNode[attr]);
|
||||||
|
for (var nodeName in exprResult) {
|
||||||
|
if (nodeName === '#current') {
|
||||||
|
checkNode(projectionNode, exprResult[nodeName]);
|
||||||
|
}
|
||||||
|
else if (filterNodeDict_1[nodeName]) {
|
||||||
|
checkNode(filterNodeDict_1[nodeName], exprResult[nodeName]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (toBeAssignNode_1[nodeName]) {
|
||||||
|
(_c = toBeAssignNode_1[nodeName]).push.apply(_c, tslib_1.__spreadArray([], tslib_1.__read(exprResult[nodeName]), false));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Object.assign(toBeAssignNode_1, (_d = {},
|
||||||
|
_d[nodeName] = exprResult[nodeName],
|
||||||
|
_d));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var rel = _this.judgeRelation(entity2, attr);
|
||||||
|
if (rel === 1) {
|
||||||
|
necessaryAttrs.push(attr);
|
||||||
|
}
|
||||||
|
else if (rel === 2) {
|
||||||
|
// entity/entityId反指
|
||||||
|
necessaryAttrs.push('entity', 'entityId');
|
||||||
|
if (!projectionNode[attr]) {
|
||||||
|
Object.assign(projectionNode, (_e = {},
|
||||||
|
_e[attr] = {
|
||||||
|
id: 1,
|
||||||
|
},
|
||||||
|
_e));
|
||||||
|
}
|
||||||
|
checkFilterNode_1(attr, filterNode[attr], projectionNode[attr]);
|
||||||
|
}
|
||||||
|
else if (typeof rel === 'string') {
|
||||||
|
necessaryAttrs.push("".concat(attr, "Id"));
|
||||||
|
if (!projectionNode[attr]) {
|
||||||
|
Object.assign(projectionNode, (_f = {},
|
||||||
|
_f[attr] = {
|
||||||
|
id: 1,
|
||||||
|
},
|
||||||
|
_f));
|
||||||
|
}
|
||||||
|
checkFilterNode_1(rel, filterNode[attr], projectionNode[attr]);
|
||||||
|
}
|
||||||
|
else if (rel instanceof Array) {
|
||||||
|
// 现在filter中还不支持一对多的语义,先放着吧
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checkNode(projectionNode, necessaryAttrs);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
checkFilterNode_1(entity, filter, data);
|
||||||
|
relevantIds = (0, filter_2.getRelevantIds)(filter);
|
||||||
|
}
|
||||||
|
// sorter感觉现在取不取影响不大,前端的list直接获取返回的ids了,先不管之
|
||||||
|
if (sorter) {
|
||||||
|
}
|
||||||
|
var toBeAssignNode2 = {}; // 用来记录在表达式中涉及到的结点
|
||||||
|
var projectionNodeDict = {};
|
||||||
|
var checkProjectionNode = function (entity2, projectionNode) {
|
||||||
|
var _a, _b, _c;
|
||||||
|
var necessaryAttrs = ['id', '$$createAt$$']; // 有的页面依赖于其它页面取数据,有时两个页面的filter的差异会导致有一个加createAt,有一个不加,此时可能产生前台取数据不完整的异常。先统一加上
|
||||||
|
for (var attr in projectionNode) {
|
||||||
|
if (attr === '#id') {
|
||||||
|
(0, assert_1.default)(!projectionNodeDict[projectionNode[attr]], "projection\u4E2D\u7ED3\u70B9\u7684id\u6709\u91CD\u590D, ".concat(projectionNode[attr]));
|
||||||
|
Object.assign(projectionNodeDict, (_a = {},
|
||||||
|
_a[projectionNode[attr]] = projectionNode,
|
||||||
|
_a));
|
||||||
|
if (toBeAssignNode2[projectionNode[attr]]) {
|
||||||
|
checkNode(projectionNode, toBeAssignNode2[projectionNode[attr]]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (attr.toLowerCase().startsWith(types_1.EXPRESSION_PREFIX)) {
|
||||||
|
var exprResult = (0, types_1.getAttrRefInExpression)(projectionNode[attr]);
|
||||||
|
for (var nodeName in exprResult) {
|
||||||
|
if (nodeName === '#current') {
|
||||||
|
checkNode(projectionNode, exprResult[nodeName]);
|
||||||
|
}
|
||||||
|
else if (projectionNodeDict[nodeName]) {
|
||||||
|
checkNode(projectionNodeDict[nodeName], exprResult[nodeName]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (toBeAssignNode2[nodeName]) {
|
||||||
|
(_b = toBeAssignNode2[nodeName]).push.apply(_b, tslib_1.__spreadArray([], tslib_1.__read(exprResult[nodeName]), false));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Object.assign(toBeAssignNode2, (_c = {},
|
||||||
|
_c[nodeName] = exprResult[nodeName],
|
||||||
|
_c));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var rel = (0, relation_1.judgeRelation)(_this.getSchema(), entity2, attr);
|
||||||
|
if (rel === 1) {
|
||||||
|
necessaryAttrs.push(attr);
|
||||||
|
}
|
||||||
|
else if (rel === 2) {
|
||||||
|
// entity/entityId反指
|
||||||
|
necessaryAttrs.push('entity', 'entityId');
|
||||||
|
checkProjectionNode(attr, projectionNode[attr]);
|
||||||
|
}
|
||||||
|
else if (typeof rel === 'string') {
|
||||||
|
necessaryAttrs.push("".concat(attr, "Id"));
|
||||||
|
checkProjectionNode(rel, projectionNode[attr]);
|
||||||
|
}
|
||||||
|
else if (rel instanceof Array && !attr.endsWith('$$aggr')) {
|
||||||
|
var data_1 = projectionNode[attr].data;
|
||||||
|
if (rel[1]) {
|
||||||
|
checkNode(data_1, [rel[1]]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
checkNode(data_1, ['entity', 'entityId']);
|
||||||
|
}
|
||||||
|
_this.reinforceSelection(rel[0], projectionNode[attr]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checkNode(projectionNode, necessaryAttrs);
|
||||||
|
}
|
||||||
|
// 如果对象中指向一对多的Modi,此时加上指向Modi的projection
|
||||||
|
if (_this.getSchema()[entity2].toModi) {
|
||||||
|
Object.assign(projectionNode, {
|
||||||
|
modi$entity: {
|
||||||
|
$entity: 'modi',
|
||||||
|
data: {
|
||||||
|
id: 1,
|
||||||
|
targetEntity: 1,
|
||||||
|
entity: 1,
|
||||||
|
entityId: 1,
|
||||||
|
action: 1,
|
||||||
|
iState: 1,
|
||||||
|
data: 1,
|
||||||
|
filter: 1,
|
||||||
|
},
|
||||||
|
filter: {
|
||||||
|
iState: 'active',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
checkProjectionNode(entity, data);
|
||||||
|
if (!sorter && relevantIds.length === 0) {
|
||||||
|
// 如果没有sorter,就给予一个按createAt逆序的sorter
|
||||||
|
Object.assign(selection, {
|
||||||
|
sorter: [
|
||||||
|
{
|
||||||
|
$attr: {
|
||||||
|
$$createAt$$: 1,
|
||||||
|
},
|
||||||
|
$direction: 'desc',
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
Object.assign(data, {
|
||||||
|
$$createAt$$: 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.selectionRewriters.forEach(function (ele) { return ele(_this.getSchema(), entity, selection); });
|
||||||
|
};
|
||||||
|
CascadeStore.prototype.reinforceOperation = function (entity, operation) {
|
||||||
|
var _this = this;
|
||||||
|
this.operationRewriters.forEach(function (ele) { return ele(_this.getSchema(), entity, operation); });
|
||||||
|
};
|
||||||
|
CascadeStore.prototype.registerOperationRewriter = function (rewriter) {
|
||||||
|
this.operationRewriters.push(rewriter);
|
||||||
|
};
|
||||||
|
CascadeStore.prototype.registerSelectionRewriter = function (rewriter) {
|
||||||
|
this.selectionRewriters.push(rewriter);
|
||||||
|
};
|
||||||
CascadeStore.prototype.destructCascadeSelect = function (entity, projection2, context, cascadeSelectFn, aggregateFn, option) {
|
CascadeStore.prototype.destructCascadeSelect = function (entity, projection2, context, cascadeSelectFn, aggregateFn, option) {
|
||||||
var _this = this;
|
var _this = this;
|
||||||
var projection = {};
|
var projection = {};
|
||||||
|
|
@ -69,6 +307,10 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
cascadeSelectionFns.push(function (result) {
|
cascadeSelectionFns.push(function (result) {
|
||||||
|
var entityIds = (0, lodash_1.uniq)(result.filter(function (ele) { return ele.entity === attr; }).map(function (ele) {
|
||||||
|
(0, assert_1.default)(ele.entityId !== null);
|
||||||
|
return ele.entityId;
|
||||||
|
}));
|
||||||
var dealWithSubRows = function (subRows) {
|
var dealWithSubRows = function (subRows) {
|
||||||
(0, assert_1.default)(subRows.length <= entityIds.length);
|
(0, assert_1.default)(subRows.length <= entityIds.length);
|
||||||
if (subRows.length < entityIds.length && !toModi) {
|
if (subRows.length < entityIds.length && !toModi) {
|
||||||
|
|
@ -101,10 +343,6 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
var entityIds = (0, lodash_1.uniq)(result.filter(function (ele) { return ele.entity === attr; }).map(function (ele) {
|
|
||||||
(0, assert_1.default)(ele.entityId !== null);
|
|
||||||
return ele.entityId;
|
|
||||||
}));
|
|
||||||
if (entityIds.length > 0) {
|
if (entityIds.length > 0) {
|
||||||
var subRows = cascadeSelectFn.call(_this, attr, {
|
var subRows = cascadeSelectFn.call(_this, attr, {
|
||||||
data: projection2[attr],
|
data: projection2[attr],
|
||||||
|
|
@ -121,8 +359,6 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
dealWithSubRows(subRows);
|
dealWithSubRows(subRows);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -161,6 +397,7 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
cascadeSelectionFns.push(function (result) {
|
cascadeSelectionFns.push(function (result) {
|
||||||
|
var ids = (0, lodash_1.uniq)(result.filter(function (ele) { return !!(ele["".concat(attr, "Id")]); }).map(function (ele) { return ele["".concat(attr, "Id")]; }));
|
||||||
var dealWithSubRows = function (subRows) {
|
var dealWithSubRows = function (subRows) {
|
||||||
(0, assert_1.default)(subRows.length <= ids.length);
|
(0, assert_1.default)(subRows.length <= ids.length);
|
||||||
if (subRows.length < ids.length && !toModi) {
|
if (subRows.length < ids.length && !toModi) {
|
||||||
|
|
@ -198,7 +435,6 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
var ids = (0, lodash_1.uniq)(result.filter(function (ele) { return !!(ele["".concat(attr, "Id")]); }).map(function (ele) { return ele["".concat(attr, "Id")]; }));
|
|
||||||
if (ids.length > 0) {
|
if (ids.length > 0) {
|
||||||
var subRows = cascadeSelectFn.call(_this, relation, {
|
var subRows = cascadeSelectFn.call(_this, relation, {
|
||||||
data: projection2[attr],
|
data: projection2[attr],
|
||||||
|
|
@ -262,6 +498,15 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
var _a;
|
var _a;
|
||||||
var ids = result.map(function (ele) { return ele.id; });
|
var ids = result.map(function (ele) { return ele.id; });
|
||||||
var dealWithSubRows = function (subRows) {
|
var dealWithSubRows = function (subRows) {
|
||||||
|
var _a;
|
||||||
|
// 这里如果result只有一行,则把返回结果直接置上,不对比外键值
|
||||||
|
// 这样做的原因是有的对象的filter会被改写掉(userId),只能临时这样处理
|
||||||
|
if (result.length == 1) {
|
||||||
|
Object.assign(result[0], (_a = {},
|
||||||
|
_a[attr] = subRows,
|
||||||
|
_a));
|
||||||
|
}
|
||||||
|
else {
|
||||||
result.forEach(function (ele) {
|
result.forEach(function (ele) {
|
||||||
var _a;
|
var _a;
|
||||||
var subRowss = subRows.filter(function (ele2) { return ele2[foreignKey_1] === ele.id; });
|
var subRowss = subRows.filter(function (ele2) { return ele2[foreignKey_1] === ele.id; });
|
||||||
|
|
@ -270,6 +515,7 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
_a[attr] = subRowss,
|
_a[attr] = subRowss,
|
||||||
_a));
|
_a));
|
||||||
});
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
if (ids.length > 0) {
|
if (ids.length > 0) {
|
||||||
var subRows = cascadeSelectFn.call(_this, entity2_1, {
|
var subRows = cascadeSelectFn.call(_this, entity2_1, {
|
||||||
|
|
@ -332,6 +578,15 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
cascadeSelectionFns.push(function (result) {
|
cascadeSelectionFns.push(function (result) {
|
||||||
var ids = result.map(function (ele) { return ele.id; });
|
var ids = result.map(function (ele) { return ele.id; });
|
||||||
var dealWithSubRows = function (subRows) {
|
var dealWithSubRows = function (subRows) {
|
||||||
|
var _a;
|
||||||
|
// 这里如果result只有一行,则把返回结果直接置上,不对比外键值
|
||||||
|
// 这样做的原因是有的对象的filter会被改写掉(userId),只能临时这样处理
|
||||||
|
if (result.length === 1) {
|
||||||
|
Object.assign(result[0], (_a = {},
|
||||||
|
_a[attr] = subRows,
|
||||||
|
_a));
|
||||||
|
}
|
||||||
|
else {
|
||||||
result.forEach(function (ele) {
|
result.forEach(function (ele) {
|
||||||
var _a;
|
var _a;
|
||||||
var subRowss = subRows.filter(function (ele2) { return ele2.entityId === ele.id; });
|
var subRowss = subRows.filter(function (ele2) { return ele2.entityId === ele.id; });
|
||||||
|
|
@ -340,6 +595,7 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
_a[attr] = subRowss,
|
_a[attr] = subRowss,
|
||||||
_a));
|
_a));
|
||||||
});
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
if (ids.length > 0) {
|
if (ids.length > 0) {
|
||||||
var subRows = cascadeSelectFn.call(_this, entity2_1, {
|
var subRows = cascadeSelectFn.call(_this, entity2_1, {
|
||||||
|
|
@ -426,7 +682,7 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
option2.modiParentEntity = entity;
|
option2.modiParentEntity = entity;
|
||||||
}
|
}
|
||||||
var _loop_2 = function (attr) {
|
var _loop_2 = function (attr) {
|
||||||
var _a, _b, _c, e_1, _d;
|
var _a, _b, _c, e_2, _d;
|
||||||
var relation = (0, relation_1.judgeRelation)(this_2.storageSchema, entity, attr);
|
var relation = (0, relation_1.judgeRelation)(this_2.storageSchema, entity, attr);
|
||||||
if (relation === 1) {
|
if (relation === 1) {
|
||||||
Object.assign(opData, (_a = {},
|
Object.assign(opData, (_a = {},
|
||||||
|
|
@ -683,17 +939,17 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
};
|
};
|
||||||
if (otmOperations instanceof Array) {
|
if (otmOperations instanceof Array) {
|
||||||
try {
|
try {
|
||||||
for (var otmOperations_1 = (e_1 = void 0, tslib_1.__values(otmOperations)), otmOperations_1_1 = otmOperations_1.next(); !otmOperations_1_1.done; otmOperations_1_1 = otmOperations_1.next()) {
|
for (var otmOperations_1 = (e_2 = void 0, tslib_1.__values(otmOperations)), otmOperations_1_1 = otmOperations_1.next(); !otmOperations_1_1.done; otmOperations_1_1 = otmOperations_1.next()) {
|
||||||
var oper = otmOperations_1_1.value;
|
var oper = otmOperations_1_1.value;
|
||||||
dealWithOneToMany(oper);
|
dealWithOneToMany(oper);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
||||||
finally {
|
finally {
|
||||||
try {
|
try {
|
||||||
if (otmOperations_1_1 && !otmOperations_1_1.done && (_d = otmOperations_1.return)) _d.call(otmOperations_1);
|
if (otmOperations_1_1 && !otmOperations_1_1.done && (_d = otmOperations_1.return)) _d.call(otmOperations_1);
|
||||||
}
|
}
|
||||||
finally { if (e_1) throw e_1.error; }
|
finally { if (e_2) throw e_2.error; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
@ -754,8 +1010,8 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
*/
|
*/
|
||||||
CascadeStore.prototype.doUpdateSingleRowAsync = function (entity, operation, context, option) {
|
CascadeStore.prototype.doUpdateSingleRowAsync = function (entity, operation, context, option) {
|
||||||
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
||||||
var data, action, operId, filter, now, _a, modiCreate, result_1, createInner, multipleCreate, data_1, data_1_1, d, createSingleOper, e_2_1, operatorId, createOper, _b, ids_1, selection, rows, modiUpsert, upsertModis, _c, originData, originId, _d, createOper, updateAttrCount, result;
|
var data, action, operId, filter, now, _a, modiCreate, result_1, createInner, multipleCreate, data_2, data_2_1, d, createSingleOper, e_3_1, operatorId, createOper, _b, ids_1, selection, rows, modiUpsert, upsertModis, _c, originData, originId, _d, createOper, updateAttrCount, result;
|
||||||
var e_2, _e, _f, _g, _h, _j, _k, _l;
|
var e_3, _e, _f, _g, _h, _j, _k, _l;
|
||||||
var _this = this;
|
var _this = this;
|
||||||
return tslib_1.__generator(this, function (_m) {
|
return tslib_1.__generator(this, function (_m) {
|
||||||
switch (_m.label) {
|
switch (_m.label) {
|
||||||
|
|
@ -766,7 +1022,7 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
switch (_a) {
|
switch (_a) {
|
||||||
case 'create': return [3 /*break*/, 1];
|
case 'create': return [3 /*break*/, 1];
|
||||||
}
|
}
|
||||||
return [3 /*break*/, 23];
|
return [3 /*break*/, 22];
|
||||||
case 1:
|
case 1:
|
||||||
this.preProcessDataCreated(entity, data);
|
this.preProcessDataCreated(entity, data);
|
||||||
if (!(option.modiParentEntity && !['modi', 'modiEntity', 'oper', 'operEntity'].includes(entity))) return [3 /*break*/, 3];
|
if (!(option.modiParentEntity && !['modi', 'modiEntity', 'oper', 'operEntity'].includes(entity))) return [3 /*break*/, 3];
|
||||||
|
|
@ -797,7 +1053,7 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
case 3:
|
case 3:
|
||||||
result_1 = 0;
|
result_1 = 0;
|
||||||
createInner = function (operation2) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
|
createInner = function (operation2) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
|
||||||
var _a, e_3;
|
var _a, e_4;
|
||||||
return tslib_1.__generator(this, function (_b) {
|
return tslib_1.__generator(this, function (_b) {
|
||||||
switch (_b.label) {
|
switch (_b.label) {
|
||||||
case 0:
|
case 0:
|
||||||
|
|
@ -808,7 +1064,7 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
result_1 = _a + _b.sent();
|
result_1 = _a + _b.sent();
|
||||||
return [3 /*break*/, 3];
|
return [3 /*break*/, 3];
|
||||||
case 2:
|
case 2:
|
||||||
e_3 = _b.sent();
|
e_4 = _b.sent();
|
||||||
/* 这段代码是处理插入时有重复的行,现在看有问题,等实际需求出现再写
|
/* 这段代码是处理插入时有重复的行,现在看有问题,等实际需求出现再写
|
||||||
if (e instanceof OakCongruentRowExists) {
|
if (e instanceof OakCongruentRowExists) {
|
||||||
if (option.allowExists) {
|
if (option.allowExists) {
|
||||||
|
|
@ -872,7 +1128,7 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} */
|
} */
|
||||||
throw e_3;
|
throw e_4;
|
||||||
case 3: return [2 /*return*/];
|
case 3: return [2 /*return*/];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -886,11 +1142,11 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
return [3 /*break*/, 12];
|
return [3 /*break*/, 12];
|
||||||
case 5:
|
case 5:
|
||||||
_m.trys.push([5, 10, 11, 12]);
|
_m.trys.push([5, 10, 11, 12]);
|
||||||
data_1 = tslib_1.__values(data), data_1_1 = data_1.next();
|
data_2 = tslib_1.__values(data), data_2_1 = data_2.next();
|
||||||
_m.label = 6;
|
_m.label = 6;
|
||||||
case 6:
|
case 6:
|
||||||
if (!!data_1_1.done) return [3 /*break*/, 9];
|
if (!!data_2_1.done) return [3 /*break*/, 9];
|
||||||
d = data_1_1.value;
|
d = data_2_1.value;
|
||||||
createSingleOper = {
|
createSingleOper = {
|
||||||
id: 'any',
|
id: 'any',
|
||||||
action: 'create',
|
action: 'create',
|
||||||
|
|
@ -901,18 +1157,18 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
_m.sent();
|
_m.sent();
|
||||||
_m.label = 8;
|
_m.label = 8;
|
||||||
case 8:
|
case 8:
|
||||||
data_1_1 = data_1.next();
|
data_2_1 = data_2.next();
|
||||||
return [3 /*break*/, 6];
|
return [3 /*break*/, 6];
|
||||||
case 9: return [3 /*break*/, 12];
|
case 9: return [3 /*break*/, 12];
|
||||||
case 10:
|
case 10:
|
||||||
e_2_1 = _m.sent();
|
e_3_1 = _m.sent();
|
||||||
e_2 = { error: e_2_1 };
|
e_3 = { error: e_3_1 };
|
||||||
return [3 /*break*/, 12];
|
return [3 /*break*/, 12];
|
||||||
case 11:
|
case 11:
|
||||||
try {
|
try {
|
||||||
if (data_1_1 && !data_1_1.done && (_e = data_1.return)) _e.call(data_1);
|
if (data_2_1 && !data_2_1.done && (_e = data_2.return)) _e.call(data_2);
|
||||||
}
|
}
|
||||||
finally { if (e_2) throw e_2.error; }
|
finally { if (e_3) throw e_3.error; }
|
||||||
return [7 /*endfinally*/];
|
return [7 /*endfinally*/];
|
||||||
case 12: return [3 /*break*/, 15];
|
case 12: return [3 /*break*/, 15];
|
||||||
case 13: return [4 /*yield*/, createInner(operation)];
|
case 13: return [4 /*yield*/, createInner(operation)];
|
||||||
|
|
@ -927,13 +1183,11 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
d: data,
|
d: data,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (!(!option.dontCreateOper && !['oper', 'operEntity', 'modiEntity', 'modi'].includes(entity))) return [3 /*break*/, 22];
|
if (!(!option.dontCreateOper && !['oper', 'operEntity', 'modiEntity', 'modi'].includes(entity))) return [3 /*break*/, 21];
|
||||||
// 按照框架要求生成Oper和OperEntity这两个内置的对象
|
// 按照框架要求生成Oper和OperEntity这两个内置的对象
|
||||||
(0, assert_1.default)(operId);
|
(0, assert_1.default)(operId);
|
||||||
return [4 /*yield*/, context.getCurrentUserId(true)];
|
operatorId = context.getCurrentUserId(true);
|
||||||
case 16:
|
if (!operatorId) return [3 /*break*/, 21];
|
||||||
operatorId = _m.sent();
|
|
||||||
if (!operatorId) return [3 /*break*/, 22];
|
|
||||||
_f = {
|
_f = {
|
||||||
id: 'dummy',
|
id: 'dummy',
|
||||||
action: 'create'
|
action: 'create'
|
||||||
|
|
@ -942,9 +1196,10 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
id: operId,
|
id: operId,
|
||||||
action: action,
|
action: action,
|
||||||
data: data,
|
data: data,
|
||||||
operatorId: operatorId
|
operatorId: operatorId,
|
||||||
|
targetEntity: entity
|
||||||
};
|
};
|
||||||
if (!(data instanceof Array)) return [3 /*break*/, 18];
|
if (!(data instanceof Array)) return [3 /*break*/, 17];
|
||||||
_h = {
|
_h = {
|
||||||
id: 'dummy',
|
id: 'dummy',
|
||||||
action: 'create'
|
action: 'create'
|
||||||
|
|
@ -957,31 +1212,31 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
_a = {};
|
_a = {};
|
||||||
return [4 /*yield*/, (0, uuid_1.generateNewIdAsync)()];
|
return [4 /*yield*/, (0, uuid_1.generateNewIdAsync)()];
|
||||||
case 1: return [2 /*return*/, (_a.id = _b.sent(),
|
case 1: return [2 /*return*/, (_a.id = _b.sent(),
|
||||||
_a.entity = entity,
|
|
||||||
_a.entityId = ele.id,
|
_a.entityId = ele.id,
|
||||||
|
_a.entity = entity,
|
||||||
_a)];
|
_a)];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}); }))];
|
}); }))];
|
||||||
case 17:
|
case 16:
|
||||||
_b = (_h.data = _m.sent(),
|
_b = (_h.data = _m.sent(),
|
||||||
_h);
|
_h);
|
||||||
return [3 /*break*/, 20];
|
return [3 /*break*/, 19];
|
||||||
case 18:
|
case 17:
|
||||||
_j = {
|
_j = {
|
||||||
id: 'dummy',
|
id: 'dummy',
|
||||||
action: 'create'
|
action: 'create'
|
||||||
};
|
};
|
||||||
_k = {};
|
_k = {};
|
||||||
return [4 /*yield*/, (0, uuid_1.generateNewIdAsync)()];
|
return [4 /*yield*/, (0, uuid_1.generateNewIdAsync)()];
|
||||||
case 19:
|
case 18:
|
||||||
_b = [(_j.data = (_k.id = _m.sent(),
|
_b = [(_j.data = (_k.id = _m.sent(),
|
||||||
_k.entity = entity,
|
|
||||||
_k.entityId = data.id,
|
_k.entityId = data.id,
|
||||||
|
_k.entity = entity,
|
||||||
_k),
|
_k),
|
||||||
_j)];
|
_j)];
|
||||||
_m.label = 20;
|
_m.label = 19;
|
||||||
case 20:
|
case 19:
|
||||||
createOper = (_f.data = (_g.operEntity$oper = _b,
|
createOper = (_f.data = (_g.operEntity$oper = _b,
|
||||||
_g),
|
_g),
|
||||||
_f);
|
_f);
|
||||||
|
|
@ -989,13 +1244,13 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
dontCollect: true,
|
dontCollect: true,
|
||||||
dontCreateOper: true,
|
dontCreateOper: true,
|
||||||
})];
|
})];
|
||||||
case 21:
|
case 20:
|
||||||
_m.sent();
|
_m.sent();
|
||||||
_m.label = 22;
|
_m.label = 21;
|
||||||
case 22: return [2 /*return*/, result_1];
|
case 21: return [2 /*return*/, result_1];
|
||||||
case 23:
|
case 22:
|
||||||
ids_1 = (0, filter_2.getRelevantIds)(filter);
|
ids_1 = (0, filter_2.getRelevantIds)(filter);
|
||||||
if (!(ids_1.length === 0)) return [3 /*break*/, 25];
|
if (!(ids_1.length === 0)) return [3 /*break*/, 24];
|
||||||
selection = {
|
selection = {
|
||||||
data: {
|
data: {
|
||||||
id: 1,
|
id: 1,
|
||||||
|
|
@ -1007,17 +1262,17 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
return [4 /*yield*/, this.selectAbjointRowAsync(entity, selection, context, {
|
return [4 /*yield*/, this.selectAbjointRowAsync(entity, selection, context, {
|
||||||
dontCollect: true,
|
dontCollect: true,
|
||||||
})];
|
})];
|
||||||
case 24:
|
case 23:
|
||||||
rows = _m.sent();
|
rows = _m.sent();
|
||||||
ids_1.push.apply(ids_1, tslib_1.__spreadArray([], tslib_1.__read((rows.map(function (ele) { return ele.id; }))), false));
|
ids_1.push.apply(ids_1, tslib_1.__spreadArray([], tslib_1.__read((rows.map(function (ele) { return ele.id; }))), false));
|
||||||
_m.label = 25;
|
_m.label = 24;
|
||||||
case 25:
|
case 24:
|
||||||
if (data) {
|
if (data) {
|
||||||
this.preProcessDataUpdated(data);
|
this.preProcessDataUpdated(data);
|
||||||
}
|
}
|
||||||
if (!(option.modiParentEntity && !['modi', 'modiEntity'].includes(entity))) return [3 /*break*/, 31];
|
if (!(option.modiParentEntity && !['modi', 'modiEntity'].includes(entity))) return [3 /*break*/, 30];
|
||||||
modiUpsert = void 0;
|
modiUpsert = void 0;
|
||||||
if (!(action !== 'remove')) return [3 /*break*/, 27];
|
if (!(action !== 'remove')) return [3 /*break*/, 26];
|
||||||
return [4 /*yield*/, this.selectAbjointRowAsync('modi', {
|
return [4 /*yield*/, this.selectAbjointRowAsync('modi', {
|
||||||
data: {
|
data: {
|
||||||
id: 1,
|
id: 1,
|
||||||
|
|
@ -1048,7 +1303,7 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
indexFrom: 0,
|
indexFrom: 0,
|
||||||
count: 1,
|
count: 1,
|
||||||
}, context, option)];
|
}, context, option)];
|
||||||
case 26:
|
case 25:
|
||||||
upsertModis = _m.sent();
|
upsertModis = _m.sent();
|
||||||
if (upsertModis.length > 0) {
|
if (upsertModis.length > 0) {
|
||||||
_c = upsertModis[0], originData = _c.data, originId = _c.id;
|
_c = upsertModis[0], originData = _c.data, originId = _c.id;
|
||||||
|
|
@ -1063,9 +1318,9 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
_m.label = 27;
|
_m.label = 26;
|
||||||
case 27:
|
case 26:
|
||||||
if (!!modiUpsert) return [3 /*break*/, 29];
|
if (!!modiUpsert) return [3 /*break*/, 28];
|
||||||
modiUpsert = {
|
modiUpsert = {
|
||||||
id: 'dummy',
|
id: 'dummy',
|
||||||
action: 'create',
|
action: 'create',
|
||||||
|
|
@ -1080,7 +1335,7 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
filter: filter,
|
filter: filter,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
if (!(ids_1.length > 0)) return [3 /*break*/, 29];
|
if (!(ids_1.length > 0)) return [3 /*break*/, 28];
|
||||||
_d = modiUpsert.data;
|
_d = modiUpsert.data;
|
||||||
_l = {
|
_l = {
|
||||||
id: 'dummy',
|
id: 'dummy',
|
||||||
|
|
@ -1100,15 +1355,15 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}); }))];
|
}); }))];
|
||||||
case 28:
|
case 27:
|
||||||
_d.modiEntity$modi = (_l.data = _m.sent(),
|
_d.modiEntity$modi = (_l.data = _m.sent(),
|
||||||
_l);
|
_l);
|
||||||
_m.label = 29;
|
_m.label = 28;
|
||||||
case 29: return [4 /*yield*/, this.cascadeUpdateAsync('modi', modiUpsert, context, option)];
|
case 28: return [4 /*yield*/, this.cascadeUpdateAsync('modi', modiUpsert, context, option)];
|
||||||
case 30:
|
case 29:
|
||||||
_m.sent();
|
_m.sent();
|
||||||
return [2 /*return*/, 1];
|
return [2 /*return*/, 1];
|
||||||
case 31:
|
case 30:
|
||||||
createOper = function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
|
createOper = function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
|
||||||
var createOper_1;
|
var createOper_1;
|
||||||
var _a, _b, _c;
|
var _a, _b, _c;
|
||||||
|
|
@ -1126,7 +1381,8 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
_b = {
|
_b = {
|
||||||
id: operId,
|
id: operId,
|
||||||
action: action,
|
action: action,
|
||||||
data: data
|
data: data,
|
||||||
|
targetEntity: entity
|
||||||
};
|
};
|
||||||
_c = {
|
_c = {
|
||||||
id: 'dummy',
|
id: 'dummy',
|
||||||
|
|
@ -1140,8 +1396,8 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
_a = {};
|
_a = {};
|
||||||
return [4 /*yield*/, (0, uuid_1.generateNewIdAsync)()];
|
return [4 /*yield*/, (0, uuid_1.generateNewIdAsync)()];
|
||||||
case 1: return [2 /*return*/, (_a.id = _b.sent(),
|
case 1: return [2 /*return*/, (_a.id = _b.sent(),
|
||||||
_a.entity = entity,
|
|
||||||
_a.entityId = ele,
|
_a.entityId = ele,
|
||||||
|
_a.entity = entity,
|
||||||
_a)];
|
_a)];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -1162,7 +1418,7 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}); };
|
}); };
|
||||||
if (!(action === 'remove')) return [3 /*break*/, 32];
|
if (!(action === 'remove')) return [3 /*break*/, 31];
|
||||||
if (!option.dontCollect) {
|
if (!option.dontCollect) {
|
||||||
context.opRecords.push({
|
context.opRecords.push({
|
||||||
a: 'r',
|
a: 'r',
|
||||||
|
|
@ -1174,10 +1430,10 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return [3 /*break*/, 36];
|
return [3 /*break*/, 35];
|
||||||
case 32:
|
case 31:
|
||||||
updateAttrCount = Object.keys(data).length;
|
updateAttrCount = Object.keys(data).length;
|
||||||
if (!(updateAttrCount > 0)) return [3 /*break*/, 33];
|
if (!(updateAttrCount > 0)) return [3 /*break*/, 32];
|
||||||
// 优化一下,如果不更新任何属性,则不实际执行
|
// 优化一下,如果不更新任何属性,则不实际执行
|
||||||
Object.assign(data, {
|
Object.assign(data, {
|
||||||
$$updateAt$$: now,
|
$$updateAt$$: now,
|
||||||
|
|
@ -1194,21 +1450,21 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return [3 /*break*/, 36];
|
return [3 /*break*/, 35];
|
||||||
case 33:
|
case 32:
|
||||||
if (!(action !== 'update')) return [3 /*break*/, 35];
|
if (!(action !== 'update')) return [3 /*break*/, 34];
|
||||||
// 如果不是update动作而是用户自定义的动作,这里还是要记录oper
|
// 如果不是update动作而是用户自定义的动作,这里还是要记录oper
|
||||||
return [4 /*yield*/, createOper()];
|
return [4 /*yield*/, createOper()];
|
||||||
case 34:
|
case 33:
|
||||||
// 如果不是update动作而是用户自定义的动作,这里还是要记录oper
|
// 如果不是update动作而是用户自定义的动作,这里还是要记录oper
|
||||||
_m.sent();
|
_m.sent();
|
||||||
return [2 /*return*/, 0];
|
return [2 /*return*/, 0];
|
||||||
case 35: return [2 /*return*/, 0];
|
case 34: return [2 /*return*/, 0];
|
||||||
case 36: return [4 /*yield*/, this.updateAbjointRowAsync(entity, operation, context, option)];
|
case 35: return [4 /*yield*/, this.updateAbjointRowAsync(entity, operation, context, option)];
|
||||||
case 37:
|
case 36:
|
||||||
result = _m.sent();
|
result = _m.sent();
|
||||||
return [4 /*yield*/, createOper()];
|
return [4 /*yield*/, createOper()];
|
||||||
case 38:
|
case 37:
|
||||||
_m.sent();
|
_m.sent();
|
||||||
return [2 /*return*/, result];
|
return [2 /*return*/, result];
|
||||||
}
|
}
|
||||||
|
|
@ -1216,7 +1472,7 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
CascadeStore.prototype.doUpdateSingleRow = function (entity, operation, context, option) {
|
CascadeStore.prototype.doUpdateSingleRow = function (entity, operation, context, option) {
|
||||||
var e_4, _a;
|
var e_5, _a;
|
||||||
var _this = this;
|
var _this = this;
|
||||||
var data = operation.data, action = operation.action, operId = operation.id, filter = operation.filter;
|
var data = operation.data, action = operation.action, operId = operation.id, filter = operation.filter;
|
||||||
var now = Date.now();
|
var now = Date.now();
|
||||||
|
|
@ -1239,8 +1495,8 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
try {
|
try {
|
||||||
for (var data_2 = tslib_1.__values(data), data_2_1 = data_2.next(); !data_2_1.done; data_2_1 = data_2.next()) {
|
for (var data_3 = tslib_1.__values(data), data_3_1 = data_3.next(); !data_3_1.done; data_3_1 = data_3.next()) {
|
||||||
var d = data_2_1.value;
|
var d = data_3_1.value;
|
||||||
var createSingleOper = {
|
var createSingleOper = {
|
||||||
id: 'any',
|
id: 'any',
|
||||||
action: 'create',
|
action: 'create',
|
||||||
|
|
@ -1249,12 +1505,12 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
createInner(createSingleOper);
|
createInner(createSingleOper);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (e_4_1) { e_4 = { error: e_4_1 }; }
|
catch (e_5_1) { e_5 = { error: e_5_1 }; }
|
||||||
finally {
|
finally {
|
||||||
try {
|
try {
|
||||||
if (data_2_1 && !data_2_1.done && (_a = data_2.return)) _a.call(data_2);
|
if (data_3_1 && !data_3_1.done && (_a = data_3.return)) _a.call(data_3);
|
||||||
}
|
}
|
||||||
finally { if (e_4) throw e_4.error; }
|
finally { if (e_5) throw e_5.error; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1284,8 +1540,8 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
CascadeStore.prototype.cascadeUpdate = function (entity, operation, context, option) {
|
CascadeStore.prototype.cascadeUpdate = function (entity, operation, context, option) {
|
||||||
var e_5, _a, e_6, _b, e_7, _c;
|
var e_6, _a, e_7, _b, e_8, _c;
|
||||||
(0, selection_1.reinforceOperation)(this.getSchema(), entity, operation);
|
this.reinforceOperation(entity, operation);
|
||||||
var action = operation.action, data = operation.data, filter = operation.filter, id = operation.id;
|
var action = operation.action, data = operation.data, filter = operation.filter, id = operation.id;
|
||||||
var opData;
|
var opData;
|
||||||
var wholeBeforeFns = [];
|
var wholeBeforeFns = [];
|
||||||
|
|
@ -1294,20 +1550,20 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
if (['create', 'create-l'].includes(action) && data instanceof Array) {
|
if (['create', 'create-l'].includes(action) && data instanceof Array) {
|
||||||
opData = [];
|
opData = [];
|
||||||
try {
|
try {
|
||||||
for (var data_3 = tslib_1.__values(data), data_3_1 = data_3.next(); !data_3_1.done; data_3_1 = data_3.next()) {
|
for (var data_4 = tslib_1.__values(data), data_4_1 = data_4.next(); !data_4_1.done; data_4_1 = data_4.next()) {
|
||||||
var d = data_3_1.value;
|
var d = data_4_1.value;
|
||||||
var _d = this.destructCascadeUpdate(entity, action, d, context, option, this.cascadeUpdate), od = _d.data, beforeFns = _d.beforeFns, afterFns = _d.afterFns;
|
var _d = this.destructCascadeUpdate(entity, action, d, context, option, this.cascadeUpdate), od = _d.data, beforeFns = _d.beforeFns, afterFns = _d.afterFns;
|
||||||
opData.push(od);
|
opData.push(od);
|
||||||
wholeBeforeFns.push.apply(wholeBeforeFns, tslib_1.__spreadArray([], tslib_1.__read(beforeFns), false));
|
wholeBeforeFns.push.apply(wholeBeforeFns, tslib_1.__spreadArray([], tslib_1.__read(beforeFns), false));
|
||||||
wholeAfterFns.push.apply(wholeAfterFns, tslib_1.__spreadArray([], tslib_1.__read(afterFns), false));
|
wholeAfterFns.push.apply(wholeAfterFns, tslib_1.__spreadArray([], tslib_1.__read(afterFns), false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (e_5_1) { e_5 = { error: e_5_1 }; }
|
catch (e_6_1) { e_6 = { error: e_6_1 }; }
|
||||||
finally {
|
finally {
|
||||||
try {
|
try {
|
||||||
if (data_3_1 && !data_3_1.done && (_a = data_3.return)) _a.call(data_3);
|
if (data_4_1 && !data_4_1.done && (_a = data_4.return)) _a.call(data_4);
|
||||||
}
|
}
|
||||||
finally { if (e_5) throw e_5.error; }
|
finally { if (e_6) throw e_6.error; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
@ -1325,12 +1581,12 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
before_1();
|
before_1();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (e_6_1) { e_6 = { error: e_6_1 }; }
|
catch (e_7_1) { e_7 = { error: e_7_1 }; }
|
||||||
finally {
|
finally {
|
||||||
try {
|
try {
|
||||||
if (wholeBeforeFns_1_1 && !wholeBeforeFns_1_1.done && (_b = wholeBeforeFns_1.return)) _b.call(wholeBeforeFns_1);
|
if (wholeBeforeFns_1_1 && !wholeBeforeFns_1_1.done && (_b = wholeBeforeFns_1.return)) _b.call(wholeBeforeFns_1);
|
||||||
}
|
}
|
||||||
finally { if (e_6) throw e_6.error; }
|
finally { if (e_7) throw e_7.error; }
|
||||||
}
|
}
|
||||||
var count = this.doUpdateSingleRow(entity, operation2, context, option);
|
var count = this.doUpdateSingleRow(entity, operation2, context, option);
|
||||||
try {
|
try {
|
||||||
|
|
@ -1339,12 +1595,12 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
after_1();
|
after_1();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (e_7_1) { e_7 = { error: e_7_1 }; }
|
catch (e_8_1) { e_8 = { error: e_8_1 }; }
|
||||||
finally {
|
finally {
|
||||||
try {
|
try {
|
||||||
if (wholeAfterFns_1_1 && !wholeAfterFns_1_1.done && (_c = wholeAfterFns_1.return)) _c.call(wholeAfterFns_1);
|
if (wholeAfterFns_1_1 && !wholeAfterFns_1_1.done && (_c = wholeAfterFns_1.return)) _c.call(wholeAfterFns_1);
|
||||||
}
|
}
|
||||||
finally { if (e_7) throw e_7.error; }
|
finally { if (e_8) throw e_8.error; }
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
@ -1357,12 +1613,12 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
*/
|
*/
|
||||||
CascadeStore.prototype.cascadeUpdateAsync = function (entity, operation, context, option) {
|
CascadeStore.prototype.cascadeUpdateAsync = function (entity, operation, context, option) {
|
||||||
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
||||||
var action, data, filter, id, opData, wholeBeforeFns, wholeAfterFns, result, data_4, data_4_1, d, _a, od, beforeFns, afterFns, _b, od, beforeFns, afterFns, operation2, wholeBeforeFns_2, wholeBeforeFns_2_1, before_2, e_8_1, count, wholeAfterFns_2, wholeAfterFns_2_1, after_2, e_9_1;
|
var action, data, filter, id, opData, wholeBeforeFns, wholeAfterFns, result, data_5, data_5_1, d, _a, od, beforeFns, afterFns, _b, od, beforeFns, afterFns, operation2, wholeBeforeFns_2, wholeBeforeFns_2_1, before_2, e_9_1, count, wholeAfterFns_2, wholeAfterFns_2_1, after_2, e_10_1;
|
||||||
var e_10, _c, e_8, _d, _e, _f, e_9, _g;
|
var e_11, _c, e_9, _d, _e, _f, e_10, _g;
|
||||||
return tslib_1.__generator(this, function (_h) {
|
return tslib_1.__generator(this, function (_h) {
|
||||||
switch (_h.label) {
|
switch (_h.label) {
|
||||||
case 0:
|
case 0:
|
||||||
(0, selection_1.reinforceOperation)(this.getSchema(), entity, operation);
|
this.reinforceOperation(entity, operation);
|
||||||
action = operation.action, data = operation.data, filter = operation.filter, id = operation.id;
|
action = operation.action, data = operation.data, filter = operation.filter, id = operation.id;
|
||||||
wholeBeforeFns = [];
|
wholeBeforeFns = [];
|
||||||
wholeAfterFns = [];
|
wholeAfterFns = [];
|
||||||
|
|
@ -1370,20 +1626,20 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
if (['create', 'create-l'].includes(action) && data instanceof Array) {
|
if (['create', 'create-l'].includes(action) && data instanceof Array) {
|
||||||
opData = [];
|
opData = [];
|
||||||
try {
|
try {
|
||||||
for (data_4 = tslib_1.__values(data), data_4_1 = data_4.next(); !data_4_1.done; data_4_1 = data_4.next()) {
|
for (data_5 = tslib_1.__values(data), data_5_1 = data_5.next(); !data_5_1.done; data_5_1 = data_5.next()) {
|
||||||
d = data_4_1.value;
|
d = data_5_1.value;
|
||||||
_a = this.destructCascadeUpdate(entity, action, d, context, option, this.cascadeUpdateAsync), od = _a.data, beforeFns = _a.beforeFns, afterFns = _a.afterFns;
|
_a = this.destructCascadeUpdate(entity, action, d, context, option, this.cascadeUpdateAsync), od = _a.data, beforeFns = _a.beforeFns, afterFns = _a.afterFns;
|
||||||
opData.push(od);
|
opData.push(od);
|
||||||
wholeBeforeFns.push.apply(wholeBeforeFns, tslib_1.__spreadArray([], tslib_1.__read(beforeFns), false));
|
wholeBeforeFns.push.apply(wholeBeforeFns, tslib_1.__spreadArray([], tslib_1.__read(beforeFns), false));
|
||||||
wholeAfterFns.push.apply(wholeAfterFns, tslib_1.__spreadArray([], tslib_1.__read(afterFns), false));
|
wholeAfterFns.push.apply(wholeAfterFns, tslib_1.__spreadArray([], tslib_1.__read(afterFns), false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (e_10_1) { e_10 = { error: e_10_1 }; }
|
catch (e_11_1) { e_11 = { error: e_11_1 }; }
|
||||||
finally {
|
finally {
|
||||||
try {
|
try {
|
||||||
if (data_4_1 && !data_4_1.done && (_c = data_4.return)) _c.call(data_4);
|
if (data_5_1 && !data_5_1.done && (_c = data_5.return)) _c.call(data_5);
|
||||||
}
|
}
|
||||||
finally { if (e_10) throw e_10.error; }
|
finally { if (e_11) throw e_11.error; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
@ -1412,14 +1668,14 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
return [3 /*break*/, 2];
|
return [3 /*break*/, 2];
|
||||||
case 5: return [3 /*break*/, 8];
|
case 5: return [3 /*break*/, 8];
|
||||||
case 6:
|
case 6:
|
||||||
e_8_1 = _h.sent();
|
e_9_1 = _h.sent();
|
||||||
e_8 = { error: e_8_1 };
|
e_9 = { error: e_9_1 };
|
||||||
return [3 /*break*/, 8];
|
return [3 /*break*/, 8];
|
||||||
case 7:
|
case 7:
|
||||||
try {
|
try {
|
||||||
if (wholeBeforeFns_2_1 && !wholeBeforeFns_2_1.done && (_d = wholeBeforeFns_2.return)) _d.call(wholeBeforeFns_2);
|
if (wholeBeforeFns_2_1 && !wholeBeforeFns_2_1.done && (_d = wholeBeforeFns_2.return)) _d.call(wholeBeforeFns_2);
|
||||||
}
|
}
|
||||||
finally { if (e_8) throw e_8.error; }
|
finally { if (e_9) throw e_9.error; }
|
||||||
return [7 /*endfinally*/];
|
return [7 /*endfinally*/];
|
||||||
case 8: return [4 /*yield*/, this.doUpdateSingleRowAsync(entity, operation2, context, option)];
|
case 8: return [4 /*yield*/, this.doUpdateSingleRowAsync(entity, operation2, context, option)];
|
||||||
case 9:
|
case 9:
|
||||||
|
|
@ -1446,14 +1702,14 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
return [3 /*break*/, 11];
|
return [3 /*break*/, 11];
|
||||||
case 14: return [3 /*break*/, 17];
|
case 14: return [3 /*break*/, 17];
|
||||||
case 15:
|
case 15:
|
||||||
e_9_1 = _h.sent();
|
e_10_1 = _h.sent();
|
||||||
e_9 = { error: e_9_1 };
|
e_10 = { error: e_10_1 };
|
||||||
return [3 /*break*/, 17];
|
return [3 /*break*/, 17];
|
||||||
case 16:
|
case 16:
|
||||||
try {
|
try {
|
||||||
if (wholeAfterFns_2_1 && !wholeAfterFns_2_1.done && (_g = wholeAfterFns_2.return)) _g.call(wholeAfterFns_2);
|
if (wholeAfterFns_2_1 && !wholeAfterFns_2_1.done && (_g = wholeAfterFns_2.return)) _g.call(wholeAfterFns_2);
|
||||||
}
|
}
|
||||||
finally { if (e_9) throw e_9.error; }
|
finally { if (e_10) throw e_10.error; }
|
||||||
return [7 /*endfinally*/];
|
return [7 /*endfinally*/];
|
||||||
case 17: return [2 /*return*/, result];
|
case 17: return [2 /*return*/, result];
|
||||||
}
|
}
|
||||||
|
|
@ -1461,7 +1717,7 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
CascadeStore.prototype.cascadeSelect = function (entity, selection, context, option) {
|
CascadeStore.prototype.cascadeSelect = function (entity, selection, context, option) {
|
||||||
(0, selection_1.reinforceSelection)(this.getSchema(), entity, selection);
|
this.reinforceSelection(entity, selection);
|
||||||
var data = selection.data, filter = selection.filter, indexFrom = selection.indexFrom, count = selection.count, sorter = selection.sorter;
|
var data = selection.data, filter = selection.filter, indexFrom = selection.indexFrom, count = selection.count, sorter = selection.sorter;
|
||||||
var _a = this.destructCascadeSelect(entity, data, context, this.cascadeSelect, this.aggregateSync, option), projection = _a.projection, cascadeSelectionFns = _a.cascadeSelectionFns;
|
var _a = this.destructCascadeSelect(entity, data, context, this.cascadeSelect, this.aggregateSync, option), projection = _a.projection, cascadeSelectionFns = _a.cascadeSelectionFns;
|
||||||
var rows = this.selectAbjointRow(entity, {
|
var rows = this.selectAbjointRow(entity, {
|
||||||
|
|
@ -1544,11 +1800,11 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
var id = row.id;
|
var id = row.id;
|
||||||
if (!entityBranch_1[id]) {
|
if (!entityBranch_1[id]) {
|
||||||
Object.assign(entityBranch_1, (_a = {},
|
Object.assign(entityBranch_1, (_a = {},
|
||||||
_a[id] = row,
|
_a[id] = (0, lodash_1.cloneDeep)(row),
|
||||||
_a));
|
_a));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Object.assign(entityBranch_1[id], row);
|
Object.assign(entityBranch_1[id], (0, lodash_1.cloneDeep)(row));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -1568,7 +1824,7 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
if (row) {
|
if (row) {
|
||||||
var id = row.id;
|
var id = row.id;
|
||||||
Object.assign(entityBranch, (_a = {},
|
Object.assign(entityBranch, (_a = {},
|
||||||
_a[id] = row,
|
_a[id] = (0, lodash_1.cloneDeep)(row),
|
||||||
_a));
|
_a));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -1583,7 +1839,7 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
return tslib_1.__generator(this, function (_b) {
|
return tslib_1.__generator(this, function (_b) {
|
||||||
switch (_b.label) {
|
switch (_b.label) {
|
||||||
case 0:
|
case 0:
|
||||||
(0, selection_1.reinforceSelection)(this.getSchema(), entity, selection);
|
this.reinforceSelection(entity, selection);
|
||||||
data = selection.data, filter = selection.filter, indexFrom = selection.indexFrom, count = selection.count, sorter = selection.sorter;
|
data = selection.data, filter = selection.filter, indexFrom = selection.indexFrom, count = selection.count, sorter = selection.sorter;
|
||||||
_a = this.destructCascadeSelect(entity, data, context, this.cascadeSelectAsync, this.aggregateAsync, option), projection = _a.projection, cascadeSelectionFns = _a.cascadeSelectionFns;
|
_a = this.destructCascadeSelect(entity, data, context, this.cascadeSelectAsync, this.aggregateAsync, option), projection = _a.projection, cascadeSelectionFns = _a.cascadeSelectionFns;
|
||||||
return [4 /*yield*/, this.selectAbjointRowAsync(entity, {
|
return [4 /*yield*/, this.selectAbjointRowAsync(entity, {
|
||||||
|
|
@ -1601,7 +1857,7 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
if (!(cascadeSelectionFns.length > 0)) return [3 /*break*/, 3];
|
if (!(cascadeSelectionFns.length > 0)) return [3 /*break*/, 3];
|
||||||
ruException_2 = [];
|
ruException_2 = [];
|
||||||
return [4 /*yield*/, Promise.all(cascadeSelectionFns.map(function (ele) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
|
return [4 /*yield*/, Promise.all(cascadeSelectionFns.map(function (ele) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
|
||||||
var e_11, rows_2;
|
var e_12, rows_2;
|
||||||
return tslib_1.__generator(this, function (_a) {
|
return tslib_1.__generator(this, function (_a) {
|
||||||
switch (_a.label) {
|
switch (_a.label) {
|
||||||
case 0:
|
case 0:
|
||||||
|
|
@ -1611,13 +1867,13 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
_a.sent();
|
_a.sent();
|
||||||
return [3 /*break*/, 3];
|
return [3 /*break*/, 3];
|
||||||
case 2:
|
case 2:
|
||||||
e_11 = _a.sent();
|
e_12 = _a.sent();
|
||||||
if (e_11 instanceof types_1.OakRowUnexistedException) {
|
if (e_12 instanceof types_1.OakRowUnexistedException) {
|
||||||
rows_2 = e_11.getRows();
|
rows_2 = e_12.getRows();
|
||||||
ruException_2.push.apply(ruException_2, tslib_1.__spreadArray([], tslib_1.__read(rows_2), false));
|
ruException_2.push.apply(ruException_2, tslib_1.__spreadArray([], tslib_1.__read(rows_2), false));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw e_11;
|
throw e_12;
|
||||||
}
|
}
|
||||||
return [3 /*break*/, 3];
|
return [3 /*break*/, 3];
|
||||||
case 3: return [2 /*return*/];
|
case 3: return [2 /*return*/];
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { EntityDict, RowStore, OperateOption, OperationResult, SelectOption, TxnOption, Context, AggregationResult } from "../types";
|
import { EntityDict, RowStore, OperateOption, OperationResult, SelectOption, TxnOption, Context, AggregationResult } from "../types";
|
||||||
export declare abstract class SyncContext<ED extends EntityDict> implements Context {
|
export declare abstract class SyncContext<ED extends EntityDict> implements Context {
|
||||||
private rowStore;
|
rowStore: SyncRowStore<ED, this>;
|
||||||
private uuid?;
|
private uuid?;
|
||||||
constructor(rowStore: SyncRowStore<ED, SyncContext<ED>>);
|
constructor(rowStore: SyncRowStore<ED, SyncContext<ED>>);
|
||||||
abstract getCurrentUserId(allowUnloggedIn?: boolean): string | undefined;
|
abstract getCurrentUserId(allowUnloggedIn?: boolean): string | undefined;
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ var TriggerExecutor = /** @class */ (function () {
|
||||||
TriggerExecutor.prototype.registerChecker = function (checker) {
|
TriggerExecutor.prototype.registerChecker = function (checker) {
|
||||||
var entity = checker.entity, action = checker.action, type = checker.type, conditionalFilter = checker.conditionalFilter;
|
var entity = checker.entity, action = checker.action, type = checker.type, conditionalFilter = checker.conditionalFilter;
|
||||||
var triggerName = "".concat(String(entity)).concat(action, "\u6743\u9650\u68C0\u67E5-").concat(this.counter++);
|
var triggerName = "".concat(String(entity)).concat(action, "\u6743\u9650\u68C0\u67E5-").concat(this.counter++);
|
||||||
var _a = (0, checker_1.translateCheckerInAsyncContext)(checker, true), fn = _a.fn, when = _a.when;
|
var _a = (0, checker_1.translateCheckerInAsyncContext)(checker), fn = _a.fn, when = _a.when;
|
||||||
var priority = type === 'data' ? Trigger_1.DATA_CHECKER_DEFAULT_PRIORITY : Trigger_1.CHECKER_DEFAULT_PRIORITY; // checker的默认优先级最低(前面的trigger可能会赋上一些相应的值)
|
var priority = type === 'data' ? Trigger_1.DATA_CHECKER_DEFAULT_PRIORITY : Trigger_1.CHECKER_DEFAULT_PRIORITY; // checker的默认优先级最低(前面的trigger可能会赋上一些相应的值)
|
||||||
var trigger = {
|
var trigger = {
|
||||||
checkerType: type,
|
checkerType: type,
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import { SyncContext } from './SyncRowStore';
|
||||||
* @param silent 如果silent,则row和relation类型的checker只会把限制条件加到查询上,而不报错(除掉create动作)
|
* @param silent 如果silent,则row和relation类型的checker只会把限制条件加到查询上,而不报错(除掉create动作)
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export declare function translateCheckerInAsyncContext<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends AsyncContext<ED>>(checker: Checker<ED, T, Cxt>, silent?: boolean): {
|
export declare function translateCheckerInAsyncContext<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends AsyncContext<ED>>(checker: Checker<ED, T, Cxt>): {
|
||||||
fn: Trigger<ED, T, Cxt>['fn'];
|
fn: Trigger<ED, T, Cxt>['fn'];
|
||||||
when: 'before' | 'after';
|
when: 'before' | 'after';
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ var uuid_1 = require("../utils/uuid");
|
||||||
* @param silent 如果silent,则row和relation类型的checker只会把限制条件加到查询上,而不报错(除掉create动作)
|
* @param silent 如果silent,则row和relation类型的checker只会把限制条件加到查询上,而不报错(除掉create动作)
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
function translateCheckerInAsyncContext(checker, silent) {
|
function translateCheckerInAsyncContext(checker) {
|
||||||
var _this = this;
|
var _this = this;
|
||||||
var entity = checker.entity, type = checker.type;
|
var entity = checker.entity, type = checker.type;
|
||||||
var when = 'before'; // 现在create的relation改成提前的expression检查了,原先是先插入再后检查,性能不行,而且select也需要实现前检查
|
var when = 'before'; // 现在create的relation改成提前的expression检查了,原先是先插入再后检查,性能不行,而且select也需要实现前检查
|
||||||
|
|
@ -65,7 +65,7 @@ function translateCheckerInAsyncContext(checker, silent) {
|
||||||
_c.label = 3;
|
_c.label = 3;
|
||||||
case 3:
|
case 3:
|
||||||
filter2 = _b;
|
filter2 = _b;
|
||||||
if (!silent) return [3 /*break*/, 4];
|
if (!['select', 'count', 'stat'].includes(action)) return [3 /*break*/, 4];
|
||||||
operation.filter = (0, filter_1.addFilterSegment)(operationFilter || {}, filter2);
|
operation.filter = (0, filter_1.addFilterSegment)(operationFilter || {}, filter2);
|
||||||
return [2 /*return*/, 0];
|
return [2 /*return*/, 0];
|
||||||
case 4: return [4 /*yield*/, (0, filter_1.checkFilterContains)(entity, context, filter2, operationFilter || {}, true)];
|
case 4: return [4 /*yield*/, (0, filter_1.checkFilterContains)(entity, context, filter2, operationFilter || {}, true)];
|
||||||
|
|
@ -135,7 +135,7 @@ function translateCheckerInAsyncContext(checker, silent) {
|
||||||
console.warn("".concat(entity, "\u5BF9\u8C61\u7684create\u7C7B\u578B\u7684checker\u4E2D\uFF0C\u5B58\u5728\u65E0\u6CD5\u8F6C\u6362\u4E3A\u8868\u8FBE\u5F0F\u5F62\u5F0F\u7684\u60C5\u51B5\uFF0C\u8BF7\u5C3D\u91CF\u4F7F\u7528authDef\u683C\u5F0F\u5B9A\u4E49\u8FD9\u7C7Bchecker"));
|
console.warn("".concat(entity, "\u5BF9\u8C61\u7684create\u7C7B\u578B\u7684checker\u4E2D\uFF0C\u5B58\u5728\u65E0\u6CD5\u8F6C\u6362\u4E3A\u8868\u8FBE\u5F0F\u5F62\u5F0F\u7684\u60C5\u51B5\uFF0C\u8BF7\u5C3D\u91CF\u4F7F\u7528authDef\u683C\u5F0F\u5B9A\u4E49\u8FD9\u7C7Bchecker"));
|
||||||
return [2 /*return*/, 0];
|
return [2 /*return*/, 0];
|
||||||
}
|
}
|
||||||
if (silent) {
|
if (['select', 'count', 'stat'].includes(action)) {
|
||||||
operation.filter = (0, filter_1.addFilterSegment)(filter || {}, result);
|
operation.filter = (0, filter_1.addFilterSegment)(filter || {}, result);
|
||||||
return [2 /*return*/, 0];
|
return [2 /*return*/, 0];
|
||||||
}
|
}
|
||||||
|
|
@ -409,7 +409,7 @@ function translateCascadeRelationFilterMaker(schema, lch, entity2, pathPrefix) {
|
||||||
counters.push.apply(counters, tslib_1.__spreadArray([], tslib_1.__read(ca2), false));
|
counters.push.apply(counters, tslib_1.__spreadArray([], tslib_1.__read(ca2), false));
|
||||||
}
|
}
|
||||||
if (filter.$or) {
|
if (filter.$or) {
|
||||||
var countersOr = filter.$and.map(function (ele) { return translateCreateFilterMaker(entity, ele, userId); });
|
var countersOr = filter.$or.map(function (ele) { return translateCreateFilterMaker(entity, ele, userId); });
|
||||||
// or也只要有一个满足就行(不能否定)
|
// or也只要有一个满足就行(不能否定)
|
||||||
var co2 = countersOr.filter(function (ele) { return !(ele instanceof Exception_1.OakUserUnpermittedException); });
|
var co2 = countersOr.filter(function (ele) { return !(ele instanceof Exception_1.OakUserUnpermittedException); });
|
||||||
counters.push.apply(counters, tslib_1.__spreadArray([], tslib_1.__read(co2), false));
|
counters.push.apply(counters, tslib_1.__spreadArray([], tslib_1.__read(co2), false));
|
||||||
|
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
import { StorageSchema } from '../types';
|
|
||||||
import { EntityDict } from '../types/Entity';
|
|
||||||
declare type SelectionRewriter<ED extends EntityDict> = (schema: StorageSchema<ED>, entity: keyof ED, selection: ED[keyof ED]['Selection']) => void;
|
|
||||||
export declare function registerSelectionRewriter<ED extends EntityDict>(rewriter: SelectionRewriter<ED>): void;
|
|
||||||
declare type OperationRewriter<ED extends EntityDict> = (schema: StorageSchema<ED>, entity: keyof ED, operate: ED[keyof ED]['Operation']) => void;
|
|
||||||
export declare function registerOperationRewriter<ED extends EntityDict>(rewriter: OperationRewriter<ED>): void;
|
|
||||||
/**
|
|
||||||
* 对selection进行一些完善,避免编程人员的疏漏
|
|
||||||
* @param selection
|
|
||||||
*/
|
|
||||||
export declare function reinforceSelection<ED extends EntityDict>(schema: StorageSchema<ED>, entity: keyof ED, selection: ED[keyof ED]['Selection']): void;
|
|
||||||
/**
|
|
||||||
* 对operation进行一些完善,作为operation算子的注入点
|
|
||||||
* @param schema
|
|
||||||
* @param entity
|
|
||||||
* @param selection
|
|
||||||
*/
|
|
||||||
export declare function reinforceOperation<ED extends EntityDict>(schema: StorageSchema<ED>, entity: keyof ED, operation: ED[keyof ED]['Operation']): void;
|
|
||||||
export {};
|
|
||||||
|
|
@ -1,265 +0,0 @@
|
||||||
"use strict";
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.reinforceOperation = exports.reinforceSelection = exports.registerOperationRewriter = exports.registerSelectionRewriter = void 0;
|
|
||||||
var tslib_1 = require("tslib");
|
|
||||||
var assert_1 = tslib_1.__importDefault(require("assert"));
|
|
||||||
var types_1 = require("../types");
|
|
||||||
var Demand_1 = require("../types/Demand");
|
|
||||||
var filter_1 = require("./filter");
|
|
||||||
var relation_1 = require("./relation");
|
|
||||||
var SelectionRewriters = [];
|
|
||||||
function registerSelectionRewriter(rewriter) {
|
|
||||||
SelectionRewriters.push(rewriter);
|
|
||||||
}
|
|
||||||
exports.registerSelectionRewriter = registerSelectionRewriter;
|
|
||||||
function getSelectionRewriters() {
|
|
||||||
return SelectionRewriters;
|
|
||||||
}
|
|
||||||
var OperationRewriters = [];
|
|
||||||
function registerOperationRewriter(rewriter) {
|
|
||||||
OperationRewriters.push(rewriter);
|
|
||||||
}
|
|
||||||
exports.registerOperationRewriter = registerOperationRewriter;
|
|
||||||
function getOperationRewriters() {
|
|
||||||
return OperationRewriters;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 对selection进行一些完善,避免编程人员的疏漏
|
|
||||||
* @param selection
|
|
||||||
*/
|
|
||||||
function reinforceSelection(schema, entity, selection) {
|
|
||||||
var filter = selection.filter, data = selection.data, sorter = selection.sorter;
|
|
||||||
var checkNode = function (projectionNode, attrs) {
|
|
||||||
attrs.forEach(function (attr) {
|
|
||||||
var _a;
|
|
||||||
if (!projectionNode.hasOwnProperty(attr)) {
|
|
||||||
Object.assign(projectionNode, (_a = {},
|
|
||||||
_a[attr] = 1,
|
|
||||||
_a));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
var relevantIds = [];
|
|
||||||
if (filter) {
|
|
||||||
var toBeAssignNode_1 = {}; // 用来记录在表达式中涉及到的结点
|
|
||||||
// filter当中所关联到的属性必须在projection中
|
|
||||||
var filterNodeDict_1 = {};
|
|
||||||
var checkFilterNode_1 = function (entity2, filterNode, projectionNode) {
|
|
||||||
var _a, e_1, _b, _c, _d, _e, _f;
|
|
||||||
var necessaryAttrs = ['id'];
|
|
||||||
for (var attr in filterNode) {
|
|
||||||
if (attr === '#id') {
|
|
||||||
(0, assert_1.default)(!filterNodeDict_1[filterNode[attr]], "projection\u4E2D\u7ED3\u70B9\u7684id\u6709\u91CD\u590D, ".concat(filterNode[attr]));
|
|
||||||
Object.assign(filterNodeDict_1, (_a = {},
|
|
||||||
_a[filterNode[attr]] = projectionNode,
|
|
||||||
_a));
|
|
||||||
if (toBeAssignNode_1[filterNode[attr]]) {
|
|
||||||
checkNode(projectionNode, toBeAssignNode_1[filterNode[attr]]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (['$and', '$or'].includes(attr)) {
|
|
||||||
try {
|
|
||||||
for (var _g = (e_1 = void 0, tslib_1.__values(filterNode[attr])), _h = _g.next(); !_h.done; _h = _g.next()) {
|
|
||||||
var node = _h.value;
|
|
||||||
checkFilterNode_1(entity2, node, projectionNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
||||||
finally {
|
|
||||||
try {
|
|
||||||
if (_h && !_h.done && (_b = _g.return)) _b.call(_g);
|
|
||||||
}
|
|
||||||
finally { if (e_1) throw e_1.error; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (attr === '$not') {
|
|
||||||
checkFilterNode_1(entity2, filterNode[attr], projectionNode);
|
|
||||||
}
|
|
||||||
else if (attr === '$text') {
|
|
||||||
// 全文检索首先要有fulltext索引,其次要把fulltext的相关属性加到projection里
|
|
||||||
var indexes = schema[entity2].indexes;
|
|
||||||
var fulltextIndex = indexes.find(function (ele) { return ele.config && ele.config.type === 'fulltext'; });
|
|
||||||
var attributes = fulltextIndex.attributes;
|
|
||||||
necessaryAttrs.push.apply(necessaryAttrs, tslib_1.__spreadArray([], tslib_1.__read((attributes.map(function (ele) { return ele.name; }))), false));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (attr.toLowerCase().startsWith(Demand_1.EXPRESSION_PREFIX)) {
|
|
||||||
var exprResult = (0, types_1.getAttrRefInExpression)(filterNode[attr]);
|
|
||||||
for (var nodeName in exprResult) {
|
|
||||||
if (nodeName === '#current') {
|
|
||||||
checkNode(projectionNode, exprResult[nodeName]);
|
|
||||||
}
|
|
||||||
else if (filterNodeDict_1[nodeName]) {
|
|
||||||
checkNode(filterNodeDict_1[nodeName], exprResult[nodeName]);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (toBeAssignNode_1[nodeName]) {
|
|
||||||
(_c = toBeAssignNode_1[nodeName]).push.apply(_c, tslib_1.__spreadArray([], tslib_1.__read(exprResult[nodeName]), false));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Object.assign(toBeAssignNode_1, (_d = {},
|
|
||||||
_d[nodeName] = exprResult[nodeName],
|
|
||||||
_d));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var rel = (0, relation_1.judgeRelation)(schema, entity2, attr);
|
|
||||||
if (rel === 1) {
|
|
||||||
necessaryAttrs.push(attr);
|
|
||||||
}
|
|
||||||
else if (rel === 2) {
|
|
||||||
// entity/entityId反指
|
|
||||||
necessaryAttrs.push('entity', 'entityId');
|
|
||||||
if (!projectionNode[attr]) {
|
|
||||||
Object.assign(projectionNode, (_e = {},
|
|
||||||
_e[attr] = {
|
|
||||||
id: 1,
|
|
||||||
},
|
|
||||||
_e));
|
|
||||||
}
|
|
||||||
checkFilterNode_1(attr, filterNode[attr], projectionNode[attr]);
|
|
||||||
}
|
|
||||||
else if (typeof rel === 'string') {
|
|
||||||
necessaryAttrs.push("".concat(attr, "Id"));
|
|
||||||
if (!projectionNode[attr]) {
|
|
||||||
Object.assign(projectionNode, (_f = {},
|
|
||||||
_f[attr] = {
|
|
||||||
id: 1,
|
|
||||||
},
|
|
||||||
_f));
|
|
||||||
}
|
|
||||||
checkFilterNode_1(rel, filterNode[attr], projectionNode[attr]);
|
|
||||||
}
|
|
||||||
else if (rel instanceof Array) {
|
|
||||||
// 现在filter中还不支持一对多的语义,先放着吧
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
checkNode(projectionNode, necessaryAttrs);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
checkFilterNode_1(entity, filter, data);
|
|
||||||
relevantIds = (0, filter_1.getRelevantIds)(filter);
|
|
||||||
}
|
|
||||||
// sorter感觉现在取不取影响不大,前端的list直接获取返回的ids了,先不管之
|
|
||||||
if (sorter) {
|
|
||||||
}
|
|
||||||
var toBeAssignNode2 = {}; // 用来记录在表达式中涉及到的结点
|
|
||||||
var projectionNodeDict = {};
|
|
||||||
var checkProjectionNode = function (entity2, projectionNode) {
|
|
||||||
var _a, _b, _c;
|
|
||||||
var necessaryAttrs = ['id', '$$createAt$$']; // 有的页面依赖于其它页面取数据,有时两个页面的filter的差异会导致有一个加createAt,有一个不加,此时可能产生前台取数据不完整的异常。先统一加上
|
|
||||||
for (var attr in projectionNode) {
|
|
||||||
if (attr === '#id') {
|
|
||||||
(0, assert_1.default)(!projectionNodeDict[projectionNode[attr]], "projection\u4E2D\u7ED3\u70B9\u7684id\u6709\u91CD\u590D, ".concat(projectionNode[attr]));
|
|
||||||
Object.assign(projectionNodeDict, (_a = {},
|
|
||||||
_a[projectionNode[attr]] = projectionNode,
|
|
||||||
_a));
|
|
||||||
if (toBeAssignNode2[projectionNode[attr]]) {
|
|
||||||
checkNode(projectionNode, toBeAssignNode2[projectionNode[attr]]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (attr.toLowerCase().startsWith(Demand_1.EXPRESSION_PREFIX)) {
|
|
||||||
var exprResult = (0, types_1.getAttrRefInExpression)(projectionNode[attr]);
|
|
||||||
for (var nodeName in exprResult) {
|
|
||||||
if (nodeName === '#current') {
|
|
||||||
checkNode(projectionNode, exprResult[nodeName]);
|
|
||||||
}
|
|
||||||
else if (projectionNodeDict[nodeName]) {
|
|
||||||
checkNode(projectionNodeDict[nodeName], exprResult[nodeName]);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (toBeAssignNode2[nodeName]) {
|
|
||||||
(_b = toBeAssignNode2[nodeName]).push.apply(_b, tslib_1.__spreadArray([], tslib_1.__read(exprResult[nodeName]), false));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Object.assign(toBeAssignNode2, (_c = {},
|
|
||||||
_c[nodeName] = exprResult[nodeName],
|
|
||||||
_c));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var rel = (0, relation_1.judgeRelation)(schema, entity2, attr);
|
|
||||||
if (rel === 1) {
|
|
||||||
necessaryAttrs.push(attr);
|
|
||||||
}
|
|
||||||
else if (rel === 2) {
|
|
||||||
// entity/entityId反指
|
|
||||||
necessaryAttrs.push('entity', 'entityId');
|
|
||||||
checkProjectionNode(attr, projectionNode[attr]);
|
|
||||||
}
|
|
||||||
else if (typeof rel === 'string') {
|
|
||||||
necessaryAttrs.push("".concat(attr, "Id"));
|
|
||||||
checkProjectionNode(rel, projectionNode[attr]);
|
|
||||||
}
|
|
||||||
else if (rel instanceof Array && !attr.endsWith('$$aggr')) {
|
|
||||||
var data_1 = projectionNode[attr].data;
|
|
||||||
if (rel[1]) {
|
|
||||||
checkNode(data_1, [rel[1]]);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
checkNode(data_1, ['entity', 'entityId']);
|
|
||||||
}
|
|
||||||
reinforceSelection(schema, rel[0], projectionNode[attr]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
checkNode(projectionNode, necessaryAttrs);
|
|
||||||
}
|
|
||||||
// 如果对象中指向一对多的Modi,此时加上指向Modi的projection
|
|
||||||
if (schema[entity2].toModi) {
|
|
||||||
Object.assign(projectionNode, {
|
|
||||||
modi$entity: {
|
|
||||||
$entity: 'modi',
|
|
||||||
data: {
|
|
||||||
id: 1,
|
|
||||||
targetEntity: 1,
|
|
||||||
entity: 1,
|
|
||||||
entityId: 1,
|
|
||||||
action: 1,
|
|
||||||
iState: 1,
|
|
||||||
data: 1,
|
|
||||||
filter: 1,
|
|
||||||
},
|
|
||||||
filter: {
|
|
||||||
iState: 'active',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
checkProjectionNode(entity, data);
|
|
||||||
if (!sorter && relevantIds.length === 0) {
|
|
||||||
// 如果没有sorter,就给予一个按createAt逆序的sorter
|
|
||||||
Object.assign(selection, {
|
|
||||||
sorter: [
|
|
||||||
{
|
|
||||||
$attr: {
|
|
||||||
$$createAt$$: 1,
|
|
||||||
},
|
|
||||||
$direction: 'desc',
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
Object.assign(data, {
|
|
||||||
$$createAt$$: 1,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
SelectionRewriters.forEach(function (ele) { return ele(schema, entity, selection); });
|
|
||||||
}
|
|
||||||
exports.reinforceSelection = reinforceSelection;
|
|
||||||
/**
|
|
||||||
* 对operation进行一些完善,作为operation算子的注入点
|
|
||||||
* @param schema
|
|
||||||
* @param entity
|
|
||||||
* @param selection
|
|
||||||
*/
|
|
||||||
function reinforceOperation(schema, entity, operation) {
|
|
||||||
OperationRewriters.forEach(function (ele) { return ele(schema, entity, operation); });
|
|
||||||
}
|
|
||||||
exports.reinforceOperation = reinforceOperation;
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
import { EntityDict } from '../types/Entity';
|
||||||
|
import { EntityDict as BaseEntityDict } from '../base-app-domain';
|
||||||
|
import { AsyncContext } from '../store/AsyncRowStore';
|
||||||
|
export declare type VaccumOperOption<ED extends EntityDict & BaseEntityDict> = {
|
||||||
|
aliveLine: number;
|
||||||
|
excludeOpers?: {
|
||||||
|
[T in keyof ED]?: ED[T]['Action'][];
|
||||||
|
};
|
||||||
|
backupDir?: string;
|
||||||
|
zip?: boolean;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* 将一定日期之前的oper对象清空
|
||||||
|
* @param option
|
||||||
|
* @param context
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export declare function vaccumOper<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED>>(option: VaccumOperOption<ED>, context: Cxt): Promise<void>;
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.vaccumOper = void 0;
|
||||||
|
var tslib_1 = require("tslib");
|
||||||
|
var vaccum_1 = require("./vaccum");
|
||||||
|
var filter_1 = require("../store/filter");
|
||||||
|
/**
|
||||||
|
* 将一定日期之前的oper对象清空
|
||||||
|
* @param option
|
||||||
|
* @param context
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
function vaccumOper(option, context) {
|
||||||
|
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
||||||
|
var aliveLine, excludeOpers, rest, operFilter, notFilters, key;
|
||||||
|
return tslib_1.__generator(this, function (_a) {
|
||||||
|
aliveLine = option.aliveLine, excludeOpers = option.excludeOpers, rest = tslib_1.__rest(option, ["aliveLine", "excludeOpers"]);
|
||||||
|
operFilter = {};
|
||||||
|
if (excludeOpers) {
|
||||||
|
notFilters = [];
|
||||||
|
for (key in excludeOpers) {
|
||||||
|
if (excludeOpers[key].length > 0) {
|
||||||
|
notFilters.push({
|
||||||
|
targetEntity: key,
|
||||||
|
action: {
|
||||||
|
$in: excludeOpers[key],
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
notFilters.push({
|
||||||
|
targetEntity: key,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (notFilters.length > 0) {
|
||||||
|
operFilter.$not = {
|
||||||
|
$or: notFilters,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [2 /*return*/, (0, vaccum_1.vaccumEntities)(tslib_1.__assign({ entities: [{
|
||||||
|
entity: 'operEntity',
|
||||||
|
aliveLine: aliveLine + 10000,
|
||||||
|
filter: {
|
||||||
|
oper: (0, filter_1.combineFilters)([operFilter, {
|
||||||
|
$$createAt$$: {
|
||||||
|
$lt: aliveLine,
|
||||||
|
}
|
||||||
|
}]),
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
entity: 'oper',
|
||||||
|
aliveLine: aliveLine,
|
||||||
|
filter: operFilter,
|
||||||
|
}] }, rest), context)];
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
exports.vaccumOper = vaccumOper;
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { EntityDict } from '../types/Entity';
|
||||||
|
import { EntityDict as BaseEntityDict } from '../base-app-domain';
|
||||||
|
import { AsyncContext } from '../store/AsyncRowStore';
|
||||||
|
declare type VaccumOptionEntity<ED extends EntityDict & BaseEntityDict, T extends keyof ED> = {
|
||||||
|
entity: T;
|
||||||
|
filter?: ED[T]['Selection']['filter'];
|
||||||
|
aliveLine: number;
|
||||||
|
};
|
||||||
|
declare type VaccumOption<ED extends EntityDict & BaseEntityDict> = {
|
||||||
|
entities: Array<VaccumOptionEntity<ED, keyof ED>>;
|
||||||
|
backupDir?: string;
|
||||||
|
zip?: boolean;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* 删除数据库中的部分数据,减少体积
|
||||||
|
* 一般只删除日志类数据
|
||||||
|
* @param option
|
||||||
|
*/
|
||||||
|
export declare function vaccumEntities<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED>>(option: VaccumOption<ED>, context: Cxt): Promise<void>;
|
||||||
|
export {};
|
||||||
|
|
@ -0,0 +1,176 @@
|
||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.vaccumEntities = void 0;
|
||||||
|
var tslib_1 = require("tslib");
|
||||||
|
var dayjs_1 = tslib_1.__importDefault(require("dayjs"));
|
||||||
|
var fs_1 = require("fs");
|
||||||
|
var filter_1 = require("../store/filter");
|
||||||
|
var node_zlib_1 = require("node:zlib");
|
||||||
|
var stream_1 = require("stream");
|
||||||
|
var uuid_1 = require("../utils/uuid");
|
||||||
|
/**
|
||||||
|
* 删除数据库中的部分数据,减少体积
|
||||||
|
* 一般只删除日志类数据
|
||||||
|
* @param option
|
||||||
|
*/
|
||||||
|
function vaccumEntities(option, context) {
|
||||||
|
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
||||||
|
var entities, backupDir, _loop_1, entities_1, entities_1_1, ele, e_1_1;
|
||||||
|
var e_1, _a;
|
||||||
|
var _this = this;
|
||||||
|
return tslib_1.__generator(this, function (_b) {
|
||||||
|
switch (_b.label) {
|
||||||
|
case 0:
|
||||||
|
entities = option.entities, backupDir = option.backupDir;
|
||||||
|
_loop_1 = function (ele) {
|
||||||
|
var entity, filter, aliveLine, filter2, zip, now, backFile, fd_1, attributes_1, projection_1, attr, count_1, appendData_1, gzip_1, source_1, destination_1, _c, _d, _e;
|
||||||
|
var _f, _g;
|
||||||
|
return tslib_1.__generator(this, function (_h) {
|
||||||
|
switch (_h.label) {
|
||||||
|
case 0:
|
||||||
|
entity = ele.entity, filter = ele.filter, aliveLine = ele.aliveLine;
|
||||||
|
filter2 = {
|
||||||
|
$$createAt$$: {
|
||||||
|
$lt: aliveLine,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
if (filter) {
|
||||||
|
filter2 = (0, filter_1.combineFilters)([filter2, filter]);
|
||||||
|
}
|
||||||
|
if (!backupDir) return [3 /*break*/, 4];
|
||||||
|
zip = option.zip;
|
||||||
|
now = (0, dayjs_1.default)();
|
||||||
|
backFile = "".concat(backupDir, "/").concat(entity, "-").concat(now.format('YYYY-MM-DD HH:mm:ss'), ".csv");
|
||||||
|
if ((0, fs_1.existsSync)(backFile)) {
|
||||||
|
(0, fs_1.rmSync)(backFile);
|
||||||
|
}
|
||||||
|
fd_1 = (0, fs_1.openSync)(backFile, 'a');
|
||||||
|
attributes_1 = ['id', '$$createAt$$', '$$updateAt$$', '$$deleteAt$$'];
|
||||||
|
projection_1 = {
|
||||||
|
id: 1,
|
||||||
|
$$createAt$$: 1,
|
||||||
|
$$updateAt$$: 1,
|
||||||
|
$$deleteAt$$: 1,
|
||||||
|
};
|
||||||
|
for (attr in context.getSchema()[entity].attributes) {
|
||||||
|
Object.assign(projection_1, (_f = {},
|
||||||
|
_f[attr] = 1,
|
||||||
|
_f));
|
||||||
|
attributes_1.push(attr);
|
||||||
|
}
|
||||||
|
(0, fs_1.appendFileSync)(fd_1, attributes_1.join(','));
|
||||||
|
(0, fs_1.appendFileSync)(fd_1, '\n');
|
||||||
|
count_1 = 0;
|
||||||
|
appendData_1 = function (minCreateAt) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
|
||||||
|
var filter3, rows, csvTxt, maxCreateAt;
|
||||||
|
return tslib_1.__generator(this, function (_a) {
|
||||||
|
switch (_a.label) {
|
||||||
|
case 0:
|
||||||
|
filter3 = (0, filter_1.combineFilters)([filter2, {
|
||||||
|
$$createAt$$: {
|
||||||
|
$gt: minCreateAt,
|
||||||
|
},
|
||||||
|
}]);
|
||||||
|
return [4 /*yield*/, context.select(entity, {
|
||||||
|
data: projection_1,
|
||||||
|
filter: filter3,
|
||||||
|
sorter: [{
|
||||||
|
$attr: {
|
||||||
|
$$createAt$$: 1,
|
||||||
|
},
|
||||||
|
$direction: 'asc'
|
||||||
|
}],
|
||||||
|
indexFrom: 0,
|
||||||
|
count: 1000,
|
||||||
|
}, { includedDeleted: true })];
|
||||||
|
case 1:
|
||||||
|
rows = _a.sent();
|
||||||
|
csvTxt = rows.map(function (row) { return attributes_1.map(function (attr) { return JSON.stringify(row[attr]); }).join(','); }).join('\n');
|
||||||
|
(0, fs_1.appendFileSync)(fd_1, csvTxt);
|
||||||
|
(0, fs_1.appendFileSync)(fd_1, '\n');
|
||||||
|
count_1 += rows.length;
|
||||||
|
if (rows.length === 1000) {
|
||||||
|
maxCreateAt = rows[999].$$createAt$$;
|
||||||
|
return [2 /*return*/, appendData_1(maxCreateAt)];
|
||||||
|
}
|
||||||
|
return [2 /*return*/];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}); };
|
||||||
|
return [4 /*yield*/, appendData_1(0)];
|
||||||
|
case 1:
|
||||||
|
_h.sent();
|
||||||
|
(0, fs_1.closeSync)(fd_1);
|
||||||
|
console.log("\u5907\u4EFD".concat(entity, "\u5BF9\u8C61\u5B8C\u6BD5\uFF0C\u5171\u5907\u4EFD\u4E86").concat(count_1, "\u884C\u6570\u636E"));
|
||||||
|
if (!(count_1 === 0)) return [3 /*break*/, 2];
|
||||||
|
(0, fs_1.rmSync)(backFile);
|
||||||
|
return [3 /*break*/, 4];
|
||||||
|
case 2:
|
||||||
|
if (!zip) return [3 /*break*/, 4];
|
||||||
|
gzip_1 = (0, node_zlib_1.createGzip)();
|
||||||
|
source_1 = (0, fs_1.createReadStream)(backFile);
|
||||||
|
destination_1 = (0, fs_1.createWriteStream)("".concat(backFile, ".zip"));
|
||||||
|
return [4 /*yield*/, new Promise(function (resolve, reject) {
|
||||||
|
(0, stream_1.pipeline)(source_1, gzip_1, destination_1, function (err) {
|
||||||
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
resolve(undefined);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})];
|
||||||
|
case 3:
|
||||||
|
_h.sent();
|
||||||
|
_h.label = 4;
|
||||||
|
case 4:
|
||||||
|
_d = (_c = context).operate;
|
||||||
|
_e = [entity];
|
||||||
|
_g = {};
|
||||||
|
return [4 /*yield*/, (0, uuid_1.generateNewIdAsync)()];
|
||||||
|
case 5:
|
||||||
|
// 将对应的数据删除
|
||||||
|
return [4 /*yield*/, _d.apply(_c, _e.concat([(_g.id = _h.sent(),
|
||||||
|
_g.action = 'remove',
|
||||||
|
_g.data = {},
|
||||||
|
_g.filter = filter2,
|
||||||
|
_g), { deletePhysically: true }]))];
|
||||||
|
case 6:
|
||||||
|
// 将对应的数据删除
|
||||||
|
_h.sent();
|
||||||
|
return [2 /*return*/];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
_b.label = 1;
|
||||||
|
case 1:
|
||||||
|
_b.trys.push([1, 6, 7, 8]);
|
||||||
|
entities_1 = tslib_1.__values(entities), entities_1_1 = entities_1.next();
|
||||||
|
_b.label = 2;
|
||||||
|
case 2:
|
||||||
|
if (!!entities_1_1.done) return [3 /*break*/, 5];
|
||||||
|
ele = entities_1_1.value;
|
||||||
|
return [5 /*yield**/, _loop_1(ele)];
|
||||||
|
case 3:
|
||||||
|
_b.sent();
|
||||||
|
_b.label = 4;
|
||||||
|
case 4:
|
||||||
|
entities_1_1 = entities_1.next();
|
||||||
|
return [3 /*break*/, 2];
|
||||||
|
case 5: return [3 /*break*/, 8];
|
||||||
|
case 6:
|
||||||
|
e_1_1 = _b.sent();
|
||||||
|
e_1 = { error: e_1_1 };
|
||||||
|
return [3 /*break*/, 8];
|
||||||
|
case 7:
|
||||||
|
try {
|
||||||
|
if (entities_1_1 && !entities_1_1.done && (_a = entities_1.return)) _a.call(entities_1);
|
||||||
|
}
|
||||||
|
finally { if (e_1) throw e_1.error; }
|
||||||
|
return [7 /*endfinally*/];
|
||||||
|
case 8: return [2 /*return*/];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
exports.vaccumEntities = vaccumEntities;
|
||||||
|
|
@ -16,10 +16,10 @@ export declare abstract class Connector<ED extends EntityDict, BackCxt extends A
|
||||||
params: any;
|
params: any;
|
||||||
context: BackCxt;
|
context: BackCxt;
|
||||||
}>;
|
}>;
|
||||||
abstract serializeResult(result: any, context: BackCxt, headers: IncomingHttpHeaders, body: any): {
|
abstract serializeResult(result: any, context: BackCxt, headers: IncomingHttpHeaders, body: any): Promise<{
|
||||||
body: any;
|
body: any;
|
||||||
headers?: Record<string, any>;
|
headers?: Record<string, any>;
|
||||||
};
|
}>;
|
||||||
abstract serializeException(exception: OakException<ED>, headers: IncomingHttpHeaders, body: any): {
|
abstract serializeException(exception: OakException<ED>, headers: IncomingHttpHeaders, body: any): {
|
||||||
body: any;
|
body: any;
|
||||||
headers?: Record<string, any>;
|
headers?: Record<string, any>;
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ export declare type OperateOption = {
|
||||||
allowExists?: boolean;
|
allowExists?: boolean;
|
||||||
modiParentId?: string;
|
modiParentId?: string;
|
||||||
modiParentEntity?: string;
|
modiParentEntity?: string;
|
||||||
|
deletePhysically?: boolean;
|
||||||
dummy?: 1;
|
dummy?: 1;
|
||||||
};
|
};
|
||||||
export declare type FormUpdateData<SH extends GeneralEntityShape> = Partial<{
|
export declare type FormUpdateData<SH extends GeneralEntityShape> = Partial<{
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,13 @@ import { StorageSchema } from './Storage';
|
||||||
export declare type TxnOption = {
|
export declare type TxnOption = {
|
||||||
isolationLevel: 'repeatable read' | 'serializable';
|
isolationLevel: 'repeatable read' | 'serializable';
|
||||||
};
|
};
|
||||||
|
export declare type SelectionRewriter<ED extends EntityDict> = (schema: StorageSchema<ED>, entity: keyof ED, selection: ED[keyof ED]['Selection']) => void;
|
||||||
|
export declare type OperationRewriter<ED extends EntityDict> = (schema: StorageSchema<ED>, entity: keyof ED, operate: ED[keyof ED]['Operation']) => void;
|
||||||
export declare abstract class RowStore<ED extends EntityDict> {
|
export declare abstract class RowStore<ED extends EntityDict> {
|
||||||
protected storageSchema: StorageSchema<ED>;
|
protected storageSchema: StorageSchema<ED>;
|
||||||
constructor(storageSchema: StorageSchema<ED>);
|
constructor(storageSchema: StorageSchema<ED>);
|
||||||
|
abstract registerOperationRewriter(rewriter: OperationRewriter<ED>): void;
|
||||||
|
abstract registerSelectionRewriter(rewriter: SelectionRewriter<ED>): void;
|
||||||
getSchema(): StorageSchema<ED>;
|
getSchema(): StorageSchema<ED>;
|
||||||
mergeOperationResult(result: OperationResult<ED>, toBeMerged: OperationResult<ED>): void;
|
mergeOperationResult(result: OperationResult<ED>, toBeMerged: OperationResult<ED>): void;
|
||||||
mergeMultipleResults(toBeMerged: OperationResult<ED>[]): OperationResult<ED>;
|
mergeMultipleResults(toBeMerged: OperationResult<ED>[]): OperationResult<ED>;
|
||||||
|
|
|
||||||
|
|
@ -24,10 +24,10 @@ export declare class SimpleConnector<ED extends EntityDict, BackCxt extends Asyn
|
||||||
params: any;
|
params: any;
|
||||||
context: BackCxt;
|
context: BackCxt;
|
||||||
}>;
|
}>;
|
||||||
serializeResult(result: any, context: BackCxt, headers: IncomingHttpHeaders, body: any): {
|
serializeResult(result: any, context: BackCxt, headers: IncomingHttpHeaders, body: any): Promise<{
|
||||||
body: any;
|
body: any;
|
||||||
headers?: Record<string, any> | undefined;
|
headers?: Record<string, any> | undefined;
|
||||||
};
|
}>;
|
||||||
serializeException(exception: OakException<ED>, headers: IncomingHttpHeaders, body: any): {
|
serializeException(exception: OakException<ED>, headers: IncomingHttpHeaders, body: any): {
|
||||||
body: any;
|
body: any;
|
||||||
headers?: Record<string, any> | undefined;
|
headers?: Record<string, any> | undefined;
|
||||||
|
|
|
||||||
|
|
@ -107,12 +107,19 @@ var SimpleConnector = /** @class */ (function (_super) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
SimpleConnector.prototype.serializeResult = function (result, context, headers, body) {
|
SimpleConnector.prototype.serializeResult = function (result, context, headers, body) {
|
||||||
|
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
||||||
|
return tslib_1.__generator(this, function (_a) {
|
||||||
|
switch (_a.label) {
|
||||||
|
case 0:
|
||||||
if (result instanceof stream_1.Stream || result instanceof Buffer) {
|
if (result instanceof stream_1.Stream || result instanceof Buffer) {
|
||||||
return {
|
return [2 /*return*/, {
|
||||||
body: result,
|
body: result,
|
||||||
};
|
}];
|
||||||
}
|
}
|
||||||
return {
|
return [4 /*yield*/, context.refineOpRecords()];
|
||||||
|
case 1:
|
||||||
|
_a.sent();
|
||||||
|
return [2 /*return*/, {
|
||||||
body: {
|
body: {
|
||||||
result: result,
|
result: result,
|
||||||
opRecords: context.opRecords,
|
opRecords: context.opRecords,
|
||||||
|
|
@ -120,7 +127,10 @@ var SimpleConnector = /** @class */ (function (_super) {
|
||||||
headers: {
|
headers: {
|
||||||
'oak-message': context.getMessage(),
|
'oak-message': context.getMessage(),
|
||||||
},
|
},
|
||||||
};
|
}];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
};
|
};
|
||||||
SimpleConnector.prototype.serializeException = function (exception, headers, body) {
|
SimpleConnector.prototype.serializeException = function (exception, headers, body) {
|
||||||
return {
|
return {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "oak-domain",
|
"name": "oak-domain",
|
||||||
"version": "2.6.6",
|
"version": "2.6.7",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "XuChang"
|
"name": "XuChang"
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ export const ACTION_CONSTANT_IN_OAK_DOMAIN = (level = 2) => {
|
||||||
|
|
||||||
export const RESERVED_ENTITIES = ['Schema', 'Filter', 'Query', 'SubQuery', 'Entity', 'Selection', 'Operation', 'File', 'Common',
|
export const RESERVED_ENTITIES = ['Schema', 'Filter', 'Query', 'SubQuery', 'Entity', 'Selection', 'Operation', 'File', 'Common',
|
||||||
'Locale', 'Projection', 'Data'];
|
'Locale', 'Projection', 'Data'];
|
||||||
|
export const ENTITY_NAME_MAX_LENGTH = 32;
|
||||||
export const STRING_LITERAL_MAX_LENGTH = 24;
|
export const STRING_LITERAL_MAX_LENGTH = 24;
|
||||||
export const NUMERICAL_LITERL_DEFAULT_PRECISION = 8;
|
export const NUMERICAL_LITERL_DEFAULT_PRECISION = 8;
|
||||||
export const NUMERICAL_LITERL_DEFAULT_SCALE = 2;
|
export const NUMERICAL_LITERL_DEFAULT_SCALE = 2;
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import {
|
||||||
NUMERICAL_LITERL_DEFAULT_SCALE,
|
NUMERICAL_LITERL_DEFAULT_SCALE,
|
||||||
INT_LITERL_DEFAULT_WIDTH,
|
INT_LITERL_DEFAULT_WIDTH,
|
||||||
LIB_OAK_DOMAIN,
|
LIB_OAK_DOMAIN,
|
||||||
|
ENTITY_NAME_MAX_LENGTH,
|
||||||
} from './env';
|
} from './env';
|
||||||
import { firstLetterLowerCase, firstLetterUpperCase } from '../utils/string';
|
import { firstLetterLowerCase, firstLetterUpperCase } from '../utils/string';
|
||||||
|
|
||||||
|
|
@ -510,6 +511,19 @@ function getStringEnumValues(filename: string, program: ts.Program, obj: string,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function checkNameLegal(filename: string, attrName: string, upperCase?: boolean) {
|
||||||
|
assert(attrName.length <= ENTITY_NAME_MAX_LENGTH, `文件「${filename}」:「${attrName}」的名称定义过长,不能超过「${ENTITY_NAME_MAX_LENGTH}」长度`);
|
||||||
|
if (upperCase) {
|
||||||
|
assert(/[A-Z][a-z|A-Z|0-9]+/i.test(attrName), `文件「${filename}」:「${attrName}」的名称必须以大写字母开始,且只能包含字母和数字`);
|
||||||
|
}
|
||||||
|
else if (upperCase === false) {
|
||||||
|
assert(/[a-z][a-z|A-Z|0-9]+/i.test(attrName), `文件「${filename}」:「${attrName}」的名称必须以小写字母开始,且只能包含字母和数字`);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assert(/[a-z|A-Z][a-z|A-Z|0-9]+/i.test(attrName), `文件「${filename}」:「${attrName}」的名称必须以字母开始,且只能包含字母和数字`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function analyzeEntity(filename: string, path: string, program: ts.Program, relativePath?: string) {
|
function analyzeEntity(filename: string, path: string, program: ts.Program, relativePath?: string) {
|
||||||
const fullPath = `${path}/${filename}`;
|
const fullPath = `${path}/${filename}`;
|
||||||
const sourceFile = program.getSourceFile(fullPath);
|
const sourceFile = program.getSourceFile(fullPath);
|
||||||
|
|
@ -521,6 +535,8 @@ function analyzeEntity(filename: string, path: string, program: ts.Program, rela
|
||||||
// removeFromRelationShip(moduleName);
|
// removeFromRelationShip(moduleName);
|
||||||
console.warn(`出现了同名的Entity定义「${moduleName}」,将使用${fullPath}取代掉默认对象,请检查新的对象结构及相关常量定义与原有的兼容,否则原有对象的相关逻辑会出现不可知异常`);
|
console.warn(`出现了同名的Entity定义「${moduleName}」,将使用${fullPath}取代掉默认对象,请检查新的对象结构及相关常量定义与原有的兼容,否则原有对象的相关逻辑会出现不可知异常`);
|
||||||
}
|
}
|
||||||
|
checkNameLegal(filename, moduleName, true);
|
||||||
|
|
||||||
const referencedSchemas: string[] = [];
|
const referencedSchemas: string[] = [];
|
||||||
const schemaAttrs: ts.TypeElement[] = [];
|
const schemaAttrs: ts.TypeElement[] = [];
|
||||||
let hasFulltextIndex: boolean = false;
|
let hasFulltextIndex: boolean = false;
|
||||||
|
|
@ -587,6 +603,7 @@ function analyzeEntity(filename: string, path: string, program: ts.Program, rela
|
||||||
(attrNode) => {
|
(attrNode) => {
|
||||||
const { type, name, questionToken } = <ts.PropertySignature>attrNode;
|
const { type, name, questionToken } = <ts.PropertySignature>attrNode;
|
||||||
const attrName = (<ts.Identifier>name).text;
|
const attrName = (<ts.Identifier>name).text;
|
||||||
|
checkNameLegal(filename, attrName, false);
|
||||||
if (ts.isTypeReferenceNode(type!)
|
if (ts.isTypeReferenceNode(type!)
|
||||||
&& ts.isIdentifier(type.typeName)) {
|
&& ts.isIdentifier(type.typeName)) {
|
||||||
if ((referencedSchemas.includes(type.typeName.text) || type.typeName.text === 'Schema')) {
|
if ((referencedSchemas.includes(type.typeName.text) || type.typeName.text === 'Schema')) {
|
||||||
|
|
@ -707,21 +724,13 @@ function analyzeEntity(filename: string, path: string, program: ts.Program, rela
|
||||||
[moduleName]: 1,
|
[moduleName]: 1,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
else if (hasEntityAttr || hasEntityIdAttr) {
|
||||||
|
throw new Error(`文件「${filename}」:属性 定义中只包含${hasEntityAttr ? 'entity' : 'entityId'},不符合定义规范。entity/entityId必须联合出现,代表不定对象的反向指针`);
|
||||||
|
}
|
||||||
beforeSchema = false;
|
beforeSchema = false;
|
||||||
|
|
||||||
// 对于不是Oper的对象,全部建立和OperEntity的反指关系
|
// 对于不是Modi和Oper的对象,全部建立和ModiEntity的反指关系
|
||||||
if (!['Oper', 'OperEntity', 'ModiEntity'].includes(moduleName)) {
|
if (!['Modi', 'Oper', 'OperEntity', 'ModiEntity'].includes(moduleName) && !toModi) {
|
||||||
if (ReversePointerRelations['OperEntity'] && !ReversePointerRelations['OperEntity'].includes(moduleName)) {
|
|
||||||
ReversePointerRelations['OperEntity'].push(moduleName);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
assign(ReversePointerRelations, {
|
|
||||||
['OperEntity']: [moduleName],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 对于不是Modi的对象,全部建立和ModiEntity的反指关系
|
|
||||||
if (!['Modi'].includes(moduleName) && !toModi) {
|
|
||||||
if (ReversePointerRelations['ModiEntity'] && !ReversePointerRelations['ModiEntity'].includes(moduleName)) {
|
if (ReversePointerRelations['ModiEntity'] && !ReversePointerRelations['ModiEntity'].includes(moduleName)) {
|
||||||
ReversePointerRelations['ModiEntity'].push(moduleName);
|
ReversePointerRelations['ModiEntity'].push(moduleName);
|
||||||
}
|
}
|
||||||
|
|
@ -730,8 +739,17 @@ function analyzeEntity(filename: string, path: string, program: ts.Program, rela
|
||||||
['ModiEntity']: [moduleName],
|
['ModiEntity']: [moduleName],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ReversePointerRelations['OperEntity'] && !ReversePointerRelations['OperEntity'].includes(moduleName)) {
|
||||||
|
ReversePointerRelations['OperEntity'].push(moduleName);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assign(ReversePointerRelations, {
|
||||||
|
['OperEntity']: [moduleName],
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (beforeSchema) {
|
else if (beforeSchema) {
|
||||||
// 本地规定的一些形状定义,直接使用
|
// 本地规定的一些形状定义,直接使用
|
||||||
|
|
@ -5479,7 +5497,7 @@ function constructAttributes(entity: string): ts.PropertyAssignment[] {
|
||||||
if (ts.isUnionTypeNode(type!)) {
|
if (ts.isUnionTypeNode(type!)) {
|
||||||
if (ts.isLiteralTypeNode(type.types[0])) {
|
if (ts.isLiteralTypeNode(type.types[0])) {
|
||||||
if (ts.isStringLiteral(type.types[0].literal)) {
|
if (ts.isStringLiteral(type.types[0].literal)) {
|
||||||
assert (enumAttributes && enumAttributes[(<ts.Identifier>name).text]);
|
assert(enumAttributes && enumAttributes[(<ts.Identifier>name).text]);
|
||||||
attrAssignments.push(
|
attrAssignments.push(
|
||||||
factory.createPropertyAssignment(
|
factory.createPropertyAssignment(
|
||||||
'type',
|
'type',
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ export interface Schema extends EntityShape {
|
||||||
filter?: Object;
|
filter?: Object;
|
||||||
extra?: Object;
|
extra?: Object;
|
||||||
operator?: User;
|
operator?: User;
|
||||||
|
targetEntity: String<32>;
|
||||||
};
|
};
|
||||||
|
|
||||||
const configuration: Configuration = {
|
const configuration: Configuration = {
|
||||||
|
|
@ -24,6 +25,7 @@ const locale: LocaleDef<Schema, '', '', {}> = {
|
||||||
filter: '选择条件',
|
filter: '选择条件',
|
||||||
extra: '其它',
|
extra: '其它',
|
||||||
operator: '操作者',
|
operator: '操作者',
|
||||||
|
targetEntity: '关联对象',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import assert from "assert";
|
||||||
import { IncomingHttpHeaders } from "http";
|
import { IncomingHttpHeaders } from "http";
|
||||||
|
|
||||||
export abstract class AsyncContext<ED extends EntityDict> implements Context {
|
export abstract class AsyncContext<ED extends EntityDict> implements Context {
|
||||||
private rowStore: AsyncRowStore<ED, this>;
|
rowStore: AsyncRowStore<ED, this>;
|
||||||
private uuid?: string;
|
private uuid?: string;
|
||||||
opRecords: OpRecord<ED>[];
|
opRecords: OpRecord<ED>[];
|
||||||
private scene?: string;
|
private scene?: string;
|
||||||
|
|
@ -15,6 +15,11 @@ export abstract class AsyncContext<ED extends EntityDict> implements Context {
|
||||||
rollback: Array<() => Promise<void>>;
|
rollback: Array<() => Promise<void>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在返回结果前调用,对数据行进行一些预处理,比如将一些敏感的列隐藏
|
||||||
|
*/
|
||||||
|
abstract refineOpRecords(): Promise<void>;
|
||||||
|
|
||||||
constructor(store: AsyncRowStore<ED, AsyncContext<ED>>, headers?: IncomingHttpHeaders) {
|
constructor(store: AsyncRowStore<ED, AsyncContext<ED>>, headers?: IncomingHttpHeaders) {
|
||||||
this.rowStore = store;
|
this.rowStore = store;
|
||||||
this.opRecords = [];
|
this.opRecords = [];
|
||||||
|
|
|
||||||
|
|
@ -4,19 +4,18 @@ import {
|
||||||
OperateOption, SelectOption, OperationResult, CreateAtAttribute, UpdateAtAttribute, AggregationResult, DeleteAtAttribute
|
OperateOption, SelectOption, OperationResult, CreateAtAttribute, UpdateAtAttribute, AggregationResult, DeleteAtAttribute
|
||||||
} from "../types/Entity";
|
} from "../types/Entity";
|
||||||
import { EntityDict as BaseEntityDict } from '../base-app-domain';
|
import { EntityDict as BaseEntityDict } from '../base-app-domain';
|
||||||
import { RowStore } from '../types/RowStore';
|
import { OperationRewriter, RowStore, SelectionRewriter } from '../types/RowStore';
|
||||||
import { StorageSchema } from '../types/Storage';
|
import { StorageSchema } from '../types/Storage';
|
||||||
import { addFilterSegment, combineFilters } from "./filter";
|
import { addFilterSegment, combineFilters } from "./filter";
|
||||||
import { judgeRelation } from "./relation";
|
import { judgeRelation } from "./relation";
|
||||||
import { OakRowUnexistedException } from "../types";
|
import { EXPRESSION_PREFIX, getAttrRefInExpression, OakRowUnexistedException } from "../types";
|
||||||
import { unset, uniq, cloneDeep, pick } from '../utils/lodash';
|
import { unset, uniq, cloneDeep, pick } from '../utils/lodash';
|
||||||
import { SyncContext } from "./SyncRowStore";
|
import { SyncContext } from "./SyncRowStore";
|
||||||
import { AsyncContext } from "./AsyncRowStore";
|
import { AsyncContext } from "./AsyncRowStore";
|
||||||
import { getRelevantIds } from "./filter";
|
import { getRelevantIds } from "./filter";
|
||||||
import { CreateOperation as CreateOperOperation } from '../base-app-domain/Oper/Schema';
|
import { CreateSingleOperation as CreateSingleOperOperation } from '../base-app-domain/Oper/Schema';
|
||||||
import { CreateOperation as CreateModiOperation, UpdateOperation as UpdateModiOperation } from '../base-app-domain/Modi/Schema';
|
import { CreateOperation as CreateModiOperation, UpdateOperation as UpdateModiOperation } from '../base-app-domain/Modi/Schema';
|
||||||
import { generateNewIdAsync } from "../utils/uuid";
|
import { generateNewIdAsync } from "../utils/uuid";
|
||||||
import { reinforceOperation, reinforceSelection } from "./selection";
|
|
||||||
|
|
||||||
/**这个用来处理级联的select和update,对不同能力的 */
|
/**这个用来处理级联的select和update,对不同能力的 */
|
||||||
export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> extends RowStore<ED> {
|
export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> extends RowStore<ED> {
|
||||||
|
|
@ -26,6 +25,252 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
|
||||||
protected abstract supportManyToOneJoin(): boolean;
|
protected abstract supportManyToOneJoin(): boolean;
|
||||||
protected abstract supportMultipleCreate(): boolean;
|
protected abstract supportMultipleCreate(): boolean;
|
||||||
|
|
||||||
|
private selectionRewriters: SelectionRewriter<any>[] = [];
|
||||||
|
private operationRewriters: OperationRewriter<any>[] = [];
|
||||||
|
|
||||||
|
private reinforceSelection(entity: keyof ED, selection: ED[keyof ED]['Selection']) {
|
||||||
|
const { filter, data, sorter } = selection;
|
||||||
|
|
||||||
|
const checkNode = (projectionNode: ED[keyof ED]['Selection']['data'], attrs: string[]) => {
|
||||||
|
attrs.forEach(
|
||||||
|
(attr) => {
|
||||||
|
if (!projectionNode.hasOwnProperty(attr)) {
|
||||||
|
Object.assign(projectionNode, {
|
||||||
|
[attr]: 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
let relevantIds: string[] = [];
|
||||||
|
if (filter) {
|
||||||
|
const toBeAssignNode: Record<string, string[]> = {}; // 用来记录在表达式中涉及到的结点
|
||||||
|
// filter当中所关联到的属性必须在projection中
|
||||||
|
const filterNodeDict: Record<string, ED[keyof ED]['Selection']['data']> = {};
|
||||||
|
const checkFilterNode = (entity2: keyof ED, filterNode: ED[keyof ED]['Selection']['filter'], projectionNode: ED[keyof ED]['Selection']['data']) => {
|
||||||
|
const necessaryAttrs: string[] = ['id'];
|
||||||
|
for (const attr in filterNode) {
|
||||||
|
if (attr === '#id') {
|
||||||
|
assert(!filterNodeDict[filterNode[attr]!], `projection中结点的id有重复, ${filterNode[attr]}`);
|
||||||
|
Object.assign(filterNodeDict, {
|
||||||
|
[filterNode[attr]!]: projectionNode,
|
||||||
|
});
|
||||||
|
if (toBeAssignNode[filterNode[attr]!]) {
|
||||||
|
checkNode(projectionNode, toBeAssignNode[filterNode[attr]!]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (['$and', '$or'].includes(attr)) {
|
||||||
|
for (const node of filterNode[attr]!) {
|
||||||
|
checkFilterNode(entity2, node, projectionNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (attr === '$not') {
|
||||||
|
checkFilterNode(entity2, filterNode[attr]!, projectionNode);
|
||||||
|
}
|
||||||
|
else if (attr === '$text') {
|
||||||
|
// 全文检索首先要有fulltext索引,其次要把fulltext的相关属性加到projection里
|
||||||
|
const { indexes } = this.getSchema()[entity2];
|
||||||
|
|
||||||
|
const fulltextIndex = indexes!.find(
|
||||||
|
ele => ele.config && ele.config.type === 'fulltext'
|
||||||
|
);
|
||||||
|
|
||||||
|
const { attributes } = fulltextIndex!;
|
||||||
|
necessaryAttrs.push(...(attributes.map(ele => ele.name as string)));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (attr.toLowerCase().startsWith(EXPRESSION_PREFIX)) {
|
||||||
|
const exprResult = getAttrRefInExpression(filterNode[attr]!);
|
||||||
|
for (const nodeName in exprResult) {
|
||||||
|
if (nodeName === '#current') {
|
||||||
|
checkNode(projectionNode, exprResult[nodeName]);
|
||||||
|
}
|
||||||
|
else if (filterNodeDict[nodeName]) {
|
||||||
|
checkNode(filterNodeDict[nodeName], exprResult[nodeName]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (toBeAssignNode[nodeName]) {
|
||||||
|
toBeAssignNode[nodeName].push(...exprResult[nodeName]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Object.assign(toBeAssignNode, {
|
||||||
|
[nodeName]: exprResult[nodeName],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const rel = this.judgeRelation(entity2, attr);
|
||||||
|
if (rel === 1) {
|
||||||
|
necessaryAttrs.push(attr);
|
||||||
|
}
|
||||||
|
else if (rel === 2) {
|
||||||
|
// entity/entityId反指
|
||||||
|
necessaryAttrs.push('entity', 'entityId');
|
||||||
|
if (!projectionNode[attr]) {
|
||||||
|
Object.assign(projectionNode, {
|
||||||
|
[attr]: {
|
||||||
|
id: 1,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
checkFilterNode(attr, filterNode[attr]!, projectionNode[attr]);
|
||||||
|
}
|
||||||
|
else if (typeof rel === 'string') {
|
||||||
|
necessaryAttrs.push(`${attr}Id`);
|
||||||
|
if (!projectionNode[attr]) {
|
||||||
|
Object.assign(projectionNode, {
|
||||||
|
[attr]: {
|
||||||
|
id: 1,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
checkFilterNode(rel, filterNode[attr]!, projectionNode[attr]);
|
||||||
|
}
|
||||||
|
else if (rel instanceof Array) {
|
||||||
|
// 现在filter中还不支持一对多的语义,先放着吧
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checkNode(projectionNode, necessaryAttrs);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
checkFilterNode(entity, filter, data);
|
||||||
|
relevantIds = getRelevantIds(filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
// sorter感觉现在取不取影响不大,前端的list直接获取返回的ids了,先不管之
|
||||||
|
if (sorter) {
|
||||||
|
}
|
||||||
|
|
||||||
|
const toBeAssignNode2: Record<string, string[]> = {}; // 用来记录在表达式中涉及到的结点
|
||||||
|
const projectionNodeDict: Record<string, ED[keyof ED]['Selection']['data']> = {};
|
||||||
|
const checkProjectionNode = (entity2: keyof ED, projectionNode: ED[keyof ED]['Selection']['data']) => {
|
||||||
|
const necessaryAttrs: string[] = ['id', '$$createAt$$']; // 有的页面依赖于其它页面取数据,有时两个页面的filter的差异会导致有一个加createAt,有一个不加,此时可能产生前台取数据不完整的异常。先统一加上
|
||||||
|
for (const attr in projectionNode) {
|
||||||
|
if (attr === '#id') {
|
||||||
|
assert(!projectionNodeDict[projectionNode[attr]!], `projection中结点的id有重复, ${projectionNode[attr]}`);
|
||||||
|
Object.assign(projectionNodeDict, {
|
||||||
|
[projectionNode[attr]!]: projectionNode,
|
||||||
|
});
|
||||||
|
if (toBeAssignNode2[projectionNode[attr]!]) {
|
||||||
|
checkNode(projectionNode, toBeAssignNode2[projectionNode[attr]!]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (attr.toLowerCase().startsWith(EXPRESSION_PREFIX)) {
|
||||||
|
const exprResult = getAttrRefInExpression(projectionNode[attr]!);
|
||||||
|
for (const nodeName in exprResult) {
|
||||||
|
if (nodeName === '#current') {
|
||||||
|
checkNode(projectionNode, exprResult[nodeName]);
|
||||||
|
}
|
||||||
|
else if (projectionNodeDict[nodeName]) {
|
||||||
|
checkNode(projectionNodeDict[nodeName], exprResult[nodeName]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (toBeAssignNode2[nodeName]) {
|
||||||
|
toBeAssignNode2[nodeName].push(...exprResult[nodeName]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Object.assign(toBeAssignNode2, {
|
||||||
|
[nodeName]: exprResult[nodeName],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const rel = judgeRelation(this.getSchema(), entity2, attr);
|
||||||
|
if (rel === 1) {
|
||||||
|
necessaryAttrs.push(attr);
|
||||||
|
}
|
||||||
|
else if (rel === 2) {
|
||||||
|
// entity/entityId反指
|
||||||
|
necessaryAttrs.push('entity', 'entityId');
|
||||||
|
checkProjectionNode(attr, projectionNode[attr]);
|
||||||
|
}
|
||||||
|
else if (typeof rel === 'string') {
|
||||||
|
necessaryAttrs.push(`${attr}Id`);
|
||||||
|
checkProjectionNode(rel, projectionNode[attr]);
|
||||||
|
}
|
||||||
|
else if (rel instanceof Array && !attr.endsWith('$$aggr')) {
|
||||||
|
const { data } = projectionNode[attr];
|
||||||
|
if (rel[1]) {
|
||||||
|
checkNode(data, [rel[1]]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
checkNode(data, ['entity', 'entityId']);
|
||||||
|
}
|
||||||
|
this.reinforceSelection(rel[0], projectionNode[attr]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checkNode(projectionNode, necessaryAttrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果对象中指向一对多的Modi,此时加上指向Modi的projection
|
||||||
|
if (this.getSchema()[entity2].toModi) {
|
||||||
|
Object.assign(projectionNode, {
|
||||||
|
modi$entity: {
|
||||||
|
$entity: 'modi',
|
||||||
|
data: {
|
||||||
|
id: 1,
|
||||||
|
targetEntity: 1,
|
||||||
|
entity: 1,
|
||||||
|
entityId: 1,
|
||||||
|
action: 1,
|
||||||
|
iState: 1,
|
||||||
|
data: 1,
|
||||||
|
filter: 1,
|
||||||
|
},
|
||||||
|
filter: {
|
||||||
|
iState: 'active',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
checkProjectionNode(entity, data);
|
||||||
|
|
||||||
|
if (!sorter && relevantIds.length === 0) {
|
||||||
|
// 如果没有sorter,就给予一个按createAt逆序的sorter
|
||||||
|
Object.assign(selection, {
|
||||||
|
sorter: [
|
||||||
|
{
|
||||||
|
$attr: {
|
||||||
|
$$createAt$$: 1,
|
||||||
|
},
|
||||||
|
$direction: 'desc',
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
Object.assign(data, {
|
||||||
|
$$createAt$$: 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.selectionRewriters.forEach(
|
||||||
|
ele => ele(this.getSchema(), entity, selection)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private reinforceOperation(entity: keyof ED, operation: ED[keyof ED]['Operation']) {
|
||||||
|
this.operationRewriters.forEach(
|
||||||
|
ele => ele(this.getSchema(), entity, operation)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public registerOperationRewriter(rewriter: OperationRewriter<ED>) {
|
||||||
|
this.operationRewriters.push(rewriter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public registerSelectionRewriter(rewriter: SelectionRewriter<ED>) {
|
||||||
|
this.selectionRewriters.push(rewriter);
|
||||||
|
}
|
||||||
|
|
||||||
protected abstract selectAbjointRow<T extends keyof ED, OP extends SelectOption, Cxt extends SyncContext<ED>>(
|
protected abstract selectAbjointRow<T extends keyof ED, OP extends SelectOption, Cxt extends SyncContext<ED>>(
|
||||||
entity: T,
|
entity: T,
|
||||||
selection: ED[T]['Selection'],
|
selection: ED[T]['Selection'],
|
||||||
|
|
@ -131,6 +376,15 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
|
||||||
else {
|
else {
|
||||||
cascadeSelectionFns.push(
|
cascadeSelectionFns.push(
|
||||||
(result) => {
|
(result) => {
|
||||||
|
const entityIds = uniq(result.filter(
|
||||||
|
ele => ele.entity === attr
|
||||||
|
).map(
|
||||||
|
ele => {
|
||||||
|
assert(ele.entityId !== null);
|
||||||
|
return ele.entityId;
|
||||||
|
}
|
||||||
|
) as string[]);
|
||||||
|
|
||||||
const dealWithSubRows = (subRows: Partial<ED[T]['Schema']>[]) => {
|
const dealWithSubRows = (subRows: Partial<ED[T]['Schema']>[]) => {
|
||||||
assert(subRows.length <= entityIds.length);
|
assert(subRows.length <= entityIds.length);
|
||||||
if (subRows.length < entityIds.length && !toModi) {
|
if (subRows.length < entityIds.length && !toModi) {
|
||||||
|
|
@ -167,14 +421,6 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
const entityIds = uniq(result.filter(
|
|
||||||
ele => ele.entity === attr
|
|
||||||
).map(
|
|
||||||
ele => {
|
|
||||||
assert(ele.entityId !== null);
|
|
||||||
return ele.entityId;
|
|
||||||
}
|
|
||||||
) as string[]);
|
|
||||||
|
|
||||||
if (entityIds.length > 0) {
|
if (entityIds.length > 0) {
|
||||||
const subRows = cascadeSelectFn.call(this, attr as any, {
|
const subRows = cascadeSelectFn.call(this, attr as any, {
|
||||||
|
|
@ -194,9 +440,6 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
|
||||||
dealWithSubRows(subRows as any);
|
dealWithSubRows(subRows as any);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -248,6 +491,12 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
|
||||||
else {
|
else {
|
||||||
cascadeSelectionFns.push(
|
cascadeSelectionFns.push(
|
||||||
(result) => {
|
(result) => {
|
||||||
|
const ids = uniq(result.filter(
|
||||||
|
ele => !!(ele[`${attr}Id`])
|
||||||
|
).map(
|
||||||
|
ele => ele[`${attr}Id`]
|
||||||
|
) as string[]);
|
||||||
|
|
||||||
const dealWithSubRows = (subRows: Partial<ED[keyof ED]['Schema']>[]) => {
|
const dealWithSubRows = (subRows: Partial<ED[keyof ED]['Schema']>[]) => {
|
||||||
assert(subRows.length <= ids.length);
|
assert(subRows.length <= ids.length);
|
||||||
if (subRows.length < ids.length && !toModi) {
|
if (subRows.length < ids.length && !toModi) {
|
||||||
|
|
@ -289,11 +538,6 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
const ids = uniq(result.filter(
|
|
||||||
ele => !!(ele[`${attr}Id`])
|
|
||||||
).map(
|
|
||||||
ele => ele[`${attr}Id`]
|
|
||||||
) as string[]);
|
|
||||||
|
|
||||||
if (ids.length > 0) {
|
if (ids.length > 0) {
|
||||||
const subRows = cascadeSelectFn.call(this, relation, {
|
const subRows = cascadeSelectFn.call(this, relation, {
|
||||||
|
|
@ -368,6 +612,14 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
|
||||||
) as string[];
|
) as string[];
|
||||||
|
|
||||||
const dealWithSubRows = (subRows: Partial<ED[keyof ED]['Schema']>[]) => {
|
const dealWithSubRows = (subRows: Partial<ED[keyof ED]['Schema']>[]) => {
|
||||||
|
// 这里如果result只有一行,则把返回结果直接置上,不对比外键值
|
||||||
|
// 这样做的原因是有的对象的filter会被改写掉(userId),只能临时这样处理
|
||||||
|
if (result.length == 1) {
|
||||||
|
Object.assign(result[0], {
|
||||||
|
[attr]: subRows,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
result.forEach(
|
result.forEach(
|
||||||
(ele) => {
|
(ele) => {
|
||||||
const subRowss = subRows.filter(
|
const subRowss = subRows.filter(
|
||||||
|
|
@ -379,6 +631,7 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (ids.length > 0) {
|
if (ids.length > 0) {
|
||||||
|
|
@ -452,6 +705,14 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
|
||||||
ele => ele.id
|
ele => ele.id
|
||||||
) as string[];
|
) as string[];
|
||||||
const dealWithSubRows = (subRows: Partial<ED[T]['Schema']>[]) => {
|
const dealWithSubRows = (subRows: Partial<ED[T]['Schema']>[]) => {
|
||||||
|
// 这里如果result只有一行,则把返回结果直接置上,不对比外键值
|
||||||
|
// 这样做的原因是有的对象的filter会被改写掉(userId),只能临时这样处理
|
||||||
|
if (result.length === 1) {
|
||||||
|
Object.assign(result[0], {
|
||||||
|
[attr]: subRows,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
result.forEach(
|
result.forEach(
|
||||||
(ele) => {
|
(ele) => {
|
||||||
const subRowss = subRows.filter(
|
const subRowss = subRows.filter(
|
||||||
|
|
@ -463,6 +724,7 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (ids.length > 0) {
|
if (ids.length > 0) {
|
||||||
|
|
@ -1038,9 +1300,9 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
|
||||||
if (!option.dontCreateOper && !['oper', 'operEntity', 'modiEntity', 'modi'].includes(entity as string)) {
|
if (!option.dontCreateOper && !['oper', 'operEntity', 'modiEntity', 'modi'].includes(entity as string)) {
|
||||||
// 按照框架要求生成Oper和OperEntity这两个内置的对象
|
// 按照框架要求生成Oper和OperEntity这两个内置的对象
|
||||||
assert(operId);
|
assert(operId);
|
||||||
const operatorId = await context.getCurrentUserId(true);
|
const operatorId = context.getCurrentUserId(true);
|
||||||
if (operatorId) {
|
if (operatorId) {
|
||||||
const createOper: CreateOperOperation = {
|
const createOper: CreateSingleOperOperation = {
|
||||||
id: 'dummy',
|
id: 'dummy',
|
||||||
action: 'create',
|
action: 'create',
|
||||||
data: {
|
data: {
|
||||||
|
|
@ -1048,6 +1310,7 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
|
||||||
action,
|
action,
|
||||||
data,
|
data,
|
||||||
operatorId,
|
operatorId,
|
||||||
|
targetEntity: entity as string,
|
||||||
operEntity$oper: data instanceof Array ? {
|
operEntity$oper: data instanceof Array ? {
|
||||||
id: 'dummy',
|
id: 'dummy',
|
||||||
action: 'create',
|
action: 'create',
|
||||||
|
|
@ -1055,8 +1318,8 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
|
||||||
data.map(
|
data.map(
|
||||||
async (ele) => ({
|
async (ele) => ({
|
||||||
id: await generateNewIdAsync(),
|
id: await generateNewIdAsync(),
|
||||||
entity: entity as string,
|
|
||||||
entityId: ele.id,
|
entityId: ele.id,
|
||||||
|
entity: entity as string,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
|
@ -1065,8 +1328,8 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
|
||||||
action: 'create',
|
action: 'create',
|
||||||
data: {
|
data: {
|
||||||
id: await generateNewIdAsync(),
|
id: await generateNewIdAsync(),
|
||||||
entity: entity as string,
|
|
||||||
entityId: (data as ED[T]['CreateSingle']['data']).id,
|
entityId: (data as ED[T]['CreateSingle']['data']).id,
|
||||||
|
entity: entity as string,
|
||||||
},
|
},
|
||||||
}]
|
}]
|
||||||
},
|
},
|
||||||
|
|
@ -1190,13 +1453,14 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
|
||||||
if (!option?.dontCreateOper && !['oper', 'operEntity', 'modiEntity', 'modi'].includes(entity as string) && ids.length > 0) {
|
if (!option?.dontCreateOper && !['oper', 'operEntity', 'modiEntity', 'modi'].includes(entity as string) && ids.length > 0) {
|
||||||
// 按照框架要求生成Oper和OperEntity这两个内置的对象
|
// 按照框架要求生成Oper和OperEntity这两个内置的对象
|
||||||
assert(operId);
|
assert(operId);
|
||||||
const createOper: CreateOperOperation = {
|
const createOper: CreateSingleOperOperation = {
|
||||||
id: 'dummy',
|
id: 'dummy',
|
||||||
action: 'create',
|
action: 'create',
|
||||||
data: {
|
data: {
|
||||||
id: operId,
|
id: operId,
|
||||||
action,
|
action,
|
||||||
data,
|
data,
|
||||||
|
targetEntity: entity as string,
|
||||||
operEntity$oper: {
|
operEntity$oper: {
|
||||||
id: 'dummy',
|
id: 'dummy',
|
||||||
action: 'create',
|
action: 'create',
|
||||||
|
|
@ -1204,8 +1468,8 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
|
||||||
ids.map(
|
ids.map(
|
||||||
async (ele) => ({
|
async (ele) => ({
|
||||||
id: await generateNewIdAsync(),
|
id: await generateNewIdAsync(),
|
||||||
entity: entity as string,
|
|
||||||
entityId: ele,
|
entityId: ele,
|
||||||
|
entity: entity as string,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
@ -1344,7 +1608,7 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
|
||||||
operation: ED[T]['Operation'],
|
operation: ED[T]['Operation'],
|
||||||
context: Cxt,
|
context: Cxt,
|
||||||
option: OP): OperationResult<ED> {
|
option: OP): OperationResult<ED> {
|
||||||
reinforceOperation(this.getSchema(), entity, operation);
|
this.reinforceOperation(entity, operation);
|
||||||
const { action, data, filter, id } = operation;
|
const { action, data, filter, id } = operation;
|
||||||
let opData: any;
|
let opData: any;
|
||||||
const wholeBeforeFns: Array<() => any> = [];
|
const wholeBeforeFns: Array<() => any> = [];
|
||||||
|
|
@ -1409,7 +1673,7 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
|
||||||
operation: ED[T]['Operation'],
|
operation: ED[T]['Operation'],
|
||||||
context: Cxt,
|
context: Cxt,
|
||||||
option: OP): Promise<OperationResult<ED>> {
|
option: OP): Promise<OperationResult<ED>> {
|
||||||
reinforceOperation(this.getSchema(), entity, operation);
|
this.reinforceOperation(entity, operation);
|
||||||
const { action, data, filter, id } = operation;
|
const { action, data, filter, id } = operation;
|
||||||
let opData: any;
|
let opData: any;
|
||||||
const wholeBeforeFns: Array<() => Promise<any>> = [];
|
const wholeBeforeFns: Array<() => Promise<any>> = [];
|
||||||
|
|
@ -1472,7 +1736,7 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
|
||||||
selection: ED[T]['Selection'],
|
selection: ED[T]['Selection'],
|
||||||
context: Cxt,
|
context: Cxt,
|
||||||
option: OP): Partial<ED[T]['Schema']>[] {
|
option: OP): Partial<ED[T]['Schema']>[] {
|
||||||
reinforceSelection(this.getSchema(), entity, selection);
|
this.reinforceSelection(entity, selection);
|
||||||
const { data, filter, indexFrom, count, sorter } = selection;
|
const { data, filter, indexFrom, count, sorter } = selection;
|
||||||
const { projection, cascadeSelectionFns } = this.destructCascadeSelect(
|
const { projection, cascadeSelectionFns } = this.destructCascadeSelect(
|
||||||
entity,
|
entity,
|
||||||
|
|
@ -1571,11 +1835,11 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
|
||||||
const { id } = row;
|
const { id } = row;
|
||||||
if (!entityBranch![id!]) {
|
if (!entityBranch![id!]) {
|
||||||
Object.assign(entityBranch!, {
|
Object.assign(entityBranch!, {
|
||||||
[id!]: row,
|
[id!]: cloneDeep(row),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Object.assign(entityBranch[id], row);
|
Object.assign(entityBranch[id], cloneDeep(row));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1597,7 +1861,7 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
|
||||||
if (row) {
|
if (row) {
|
||||||
const { id } = row as { id: string };
|
const { id } = row as { id: string };
|
||||||
Object.assign(entityBranch!, {
|
Object.assign(entityBranch!, {
|
||||||
[id!]: row,
|
[id!]: cloneDeep(row),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1612,7 +1876,7 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
|
||||||
selection: ED[T]['Selection'],
|
selection: ED[T]['Selection'],
|
||||||
context: Cxt,
|
context: Cxt,
|
||||||
option: OP): Promise<Partial<ED[T]['Schema']>[]> {
|
option: OP): Promise<Partial<ED[T]['Schema']>[]> {
|
||||||
reinforceSelection(this.getSchema(), entity, selection);
|
this.reinforceSelection(entity, selection);
|
||||||
const { data, filter, indexFrom, count, sorter } = selection;
|
const { data, filter, indexFrom, count, sorter } = selection;
|
||||||
const { projection, cascadeSelectionFns } = this.destructCascadeSelect(
|
const { projection, cascadeSelectionFns } = this.destructCascadeSelect(
|
||||||
entity,
|
entity,
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import assert from 'assert';
|
||||||
import { EntityDict, RowStore, OperateOption, OperationResult, SelectOption, TxnOption, Context, AggregationResult } from "../types";
|
import { EntityDict, RowStore, OperateOption, OperationResult, SelectOption, TxnOption, Context, AggregationResult } from "../types";
|
||||||
|
|
||||||
export abstract class SyncContext<ED extends EntityDict> implements Context {
|
export abstract class SyncContext<ED extends EntityDict> implements Context {
|
||||||
private rowStore: SyncRowStore<ED, this>;
|
rowStore: SyncRowStore<ED, this>;
|
||||||
private uuid?: string;
|
private uuid?: string;
|
||||||
constructor(rowStore: SyncRowStore<ED, SyncContext<ED>>) {
|
constructor(rowStore: SyncRowStore<ED, SyncContext<ED>>) {
|
||||||
this.rowStore = rowStore;
|
this.rowStore = rowStore;
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ export class TriggerExecutor<ED extends EntityDict & BaseEntityDict> {
|
||||||
registerChecker<T extends keyof ED, Cxt extends AsyncContext<ED>>(checker: Checker<ED, T, Cxt>): void {
|
registerChecker<T extends keyof ED, Cxt extends AsyncContext<ED>>(checker: Checker<ED, T, Cxt>): void {
|
||||||
const { entity, action, type, conditionalFilter } = checker;
|
const { entity, action, type, conditionalFilter } = checker;
|
||||||
const triggerName = `${String(entity)}${action}权限检查-${this.counter++}`;
|
const triggerName = `${String(entity)}${action}权限检查-${this.counter++}`;
|
||||||
const { fn, when } = translateCheckerInAsyncContext(checker, true);
|
const { fn, when } = translateCheckerInAsyncContext(checker);
|
||||||
const priority = type === 'data' ? DATA_CHECKER_DEFAULT_PRIORITY : CHECKER_DEFAULT_PRIORITY; // checker的默认优先级最低(前面的trigger可能会赋上一些相应的值)
|
const priority = type === 'data' ? DATA_CHECKER_DEFAULT_PRIORITY : CHECKER_DEFAULT_PRIORITY; // checker的默认优先级最低(前面的trigger可能会赋上一些相应的值)
|
||||||
const trigger = {
|
const trigger = {
|
||||||
checkerType: type,
|
checkerType: type,
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ export function translateCheckerInAsyncContext<
|
||||||
ED extends EntityDict & BaseEntityDict,
|
ED extends EntityDict & BaseEntityDict,
|
||||||
T extends keyof ED,
|
T extends keyof ED,
|
||||||
Cxt extends AsyncContext<ED>
|
Cxt extends AsyncContext<ED>
|
||||||
>(checker: Checker<ED, T, Cxt>, silent?: boolean): {
|
>(checker: Checker<ED, T, Cxt>): {
|
||||||
fn: Trigger<ED, T, Cxt>['fn'];
|
fn: Trigger<ED, T, Cxt>['fn'];
|
||||||
when: 'before' | 'after';
|
when: 'before' | 'after';
|
||||||
} {
|
} {
|
||||||
|
|
@ -48,7 +48,7 @@ export function translateCheckerInAsyncContext<
|
||||||
const fn = (async ({ operation }, context, option) => {
|
const fn = (async ({ operation }, context, option) => {
|
||||||
const { filter: operationFilter, action } = operation;
|
const { filter: operationFilter, action } = operation;
|
||||||
const filter2 = typeof filter === 'function' ? await (filter as Function)(operation, context, option) : filter;
|
const filter2 = typeof filter === 'function' ? await (filter as Function)(operation, context, option) : filter;
|
||||||
if (silent) {
|
if (['select', 'count', 'stat'].includes(action)) {
|
||||||
operation.filter = addFilterSegment(operationFilter || {}, filter2);
|
operation.filter = addFilterSegment(operationFilter || {}, filter2);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -106,7 +106,7 @@ export function translateCheckerInAsyncContext<
|
||||||
console.warn(`${entity as string}对象的create类型的checker中,存在无法转换为表达式形式的情况,请尽量使用authDef格式定义这类checker`);
|
console.warn(`${entity as string}对象的create类型的checker中,存在无法转换为表达式形式的情况,请尽量使用authDef格式定义这类checker`);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (silent) {
|
if (['select', 'count', 'stat'].includes(action)) {
|
||||||
operation.filter = addFilterSegment(filter || {}, result);
|
operation.filter = addFilterSegment(filter || {}, result);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -405,7 +405,7 @@ function translateCascadeRelationFilterMaker<ED extends EntityDict & BaseEntityD
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filter.$or) {
|
if (filter.$or) {
|
||||||
const countersOr = filter.$and.map(
|
const countersOr = filter.$or.map(
|
||||||
(ele: ED[keyof ED]['Selection']['filter']) => translateCreateFilterMaker(entity, ele, userId)
|
(ele: ED[keyof ED]['Selection']['filter']) => translateCreateFilterMaker(entity, ele, userId)
|
||||||
) as ReturnType<typeof translateCreateFilterMaker>[];
|
) as ReturnType<typeof translateCreateFilterMaker>[];
|
||||||
// or也只要有一个满足就行(不能否定)
|
// or也只要有一个满足就行(不能否定)
|
||||||
|
|
|
||||||
|
|
@ -1,275 +0,0 @@
|
||||||
import assert from 'assert';
|
|
||||||
import { getAttrRefInExpression, StorageSchema } from '../types';
|
|
||||||
import { EXPRESSION_PREFIX } from '../types/Demand';
|
|
||||||
import { EntityDict } from '../types/Entity';
|
|
||||||
import { getRelevantIds } from './filter';
|
|
||||||
import { judgeRelation } from './relation';
|
|
||||||
|
|
||||||
type SelectionRewriter<ED extends EntityDict> = (schema: StorageSchema<ED>, entity: keyof ED, selection: ED[keyof ED]['Selection']) => void;
|
|
||||||
|
|
||||||
const SelectionRewriters: SelectionRewriter<any>[] = [];
|
|
||||||
|
|
||||||
export function registerSelectionRewriter<ED extends EntityDict>(rewriter: SelectionRewriter<ED>) {
|
|
||||||
SelectionRewriters.push(rewriter);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getSelectionRewriters<ED extends EntityDict>() {
|
|
||||||
return SelectionRewriters as SelectionRewriter<ED>[];
|
|
||||||
}
|
|
||||||
|
|
||||||
type OperationRewriter<ED extends EntityDict> = (schema: StorageSchema<ED>, entity: keyof ED, operate: ED[keyof ED]['Operation']) => void;
|
|
||||||
|
|
||||||
const OperationRewriters: OperationRewriter<any>[] = [];
|
|
||||||
|
|
||||||
export function registerOperationRewriter<ED extends EntityDict>(rewriter: OperationRewriter<ED>) {
|
|
||||||
OperationRewriters.push(rewriter);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getOperationRewriters<ED extends EntityDict>() {
|
|
||||||
return OperationRewriters as OperationRewriter<ED>[];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 对selection进行一些完善,避免编程人员的疏漏
|
|
||||||
* @param selection
|
|
||||||
*/
|
|
||||||
export function reinforceSelection<ED extends EntityDict>(schema: StorageSchema<ED>, entity: keyof ED, selection: ED[keyof ED]['Selection']) {
|
|
||||||
const { filter, data, sorter } = selection;
|
|
||||||
|
|
||||||
const checkNode = (projectionNode: ED[keyof ED]['Selection']['data'], attrs: string[]) => {
|
|
||||||
attrs.forEach(
|
|
||||||
(attr) => {
|
|
||||||
if (!projectionNode.hasOwnProperty(attr)) {
|
|
||||||
Object.assign(projectionNode, {
|
|
||||||
[attr]: 1,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
let relevantIds: string[] = [];
|
|
||||||
if (filter) {
|
|
||||||
const toBeAssignNode: Record<string, string[]> = {}; // 用来记录在表达式中涉及到的结点
|
|
||||||
// filter当中所关联到的属性必须在projection中
|
|
||||||
const filterNodeDict: Record<string, ED[keyof ED]['Selection']['data']> = {};
|
|
||||||
const checkFilterNode = (entity2: keyof ED, filterNode: ED[keyof ED]['Selection']['filter'], projectionNode: ED[keyof ED]['Selection']['data']) => {
|
|
||||||
const necessaryAttrs: string[] = ['id'];
|
|
||||||
for (const attr in filterNode) {
|
|
||||||
if (attr === '#id') {
|
|
||||||
assert(!filterNodeDict[filterNode[attr]!], `projection中结点的id有重复, ${filterNode[attr]}`);
|
|
||||||
Object.assign(filterNodeDict, {
|
|
||||||
[filterNode[attr]!]: projectionNode,
|
|
||||||
});
|
|
||||||
if (toBeAssignNode[filterNode[attr]!]) {
|
|
||||||
checkNode(projectionNode, toBeAssignNode[filterNode[attr]!]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (['$and', '$or'].includes(attr)) {
|
|
||||||
for (const node of filterNode[attr]!) {
|
|
||||||
checkFilterNode(entity2, node, projectionNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (attr === '$not') {
|
|
||||||
checkFilterNode(entity2, filterNode[attr]!, projectionNode);
|
|
||||||
}
|
|
||||||
else if (attr === '$text') {
|
|
||||||
// 全文检索首先要有fulltext索引,其次要把fulltext的相关属性加到projection里
|
|
||||||
const { indexes } = schema[entity2];
|
|
||||||
|
|
||||||
const fulltextIndex = indexes!.find(
|
|
||||||
ele => ele.config && ele.config.type === 'fulltext'
|
|
||||||
);
|
|
||||||
|
|
||||||
const { attributes } = fulltextIndex!;
|
|
||||||
necessaryAttrs.push(...(attributes.map(ele => ele.name as string)));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (attr.toLowerCase().startsWith(EXPRESSION_PREFIX)) {
|
|
||||||
const exprResult = getAttrRefInExpression(filterNode[attr]!);
|
|
||||||
for (const nodeName in exprResult) {
|
|
||||||
if (nodeName === '#current') {
|
|
||||||
checkNode(projectionNode, exprResult[nodeName]);
|
|
||||||
}
|
|
||||||
else if (filterNodeDict[nodeName]) {
|
|
||||||
checkNode(filterNodeDict[nodeName], exprResult[nodeName]);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (toBeAssignNode[nodeName]) {
|
|
||||||
toBeAssignNode[nodeName].push(...exprResult[nodeName]);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Object.assign(toBeAssignNode, {
|
|
||||||
[nodeName]: exprResult[nodeName],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
const rel = judgeRelation(schema, entity2, attr);
|
|
||||||
if (rel === 1) {
|
|
||||||
necessaryAttrs.push(attr);
|
|
||||||
}
|
|
||||||
else if (rel === 2) {
|
|
||||||
// entity/entityId反指
|
|
||||||
necessaryAttrs.push('entity', 'entityId');
|
|
||||||
if (!projectionNode[attr]) {
|
|
||||||
Object.assign(projectionNode, {
|
|
||||||
[attr]: {
|
|
||||||
id: 1,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
checkFilterNode(attr, filterNode[attr]!, projectionNode[attr]);
|
|
||||||
}
|
|
||||||
else if (typeof rel === 'string') {
|
|
||||||
necessaryAttrs.push(`${attr}Id`);
|
|
||||||
if (!projectionNode[attr]) {
|
|
||||||
Object.assign(projectionNode, {
|
|
||||||
[attr]: {
|
|
||||||
id: 1,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
checkFilterNode(rel, filterNode[attr]!, projectionNode[attr]);
|
|
||||||
}
|
|
||||||
else if (rel instanceof Array) {
|
|
||||||
// 现在filter中还不支持一对多的语义,先放着吧
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
checkNode(projectionNode, necessaryAttrs);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
checkFilterNode(entity, filter, data);
|
|
||||||
relevantIds = getRelevantIds(filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
// sorter感觉现在取不取影响不大,前端的list直接获取返回的ids了,先不管之
|
|
||||||
if (sorter) {
|
|
||||||
}
|
|
||||||
|
|
||||||
const toBeAssignNode2: Record<string, string[]> = {}; // 用来记录在表达式中涉及到的结点
|
|
||||||
const projectionNodeDict: Record<string, ED[keyof ED]['Selection']['data']> = {};
|
|
||||||
const checkProjectionNode = (entity2: keyof ED, projectionNode: ED[keyof ED]['Selection']['data']) => {
|
|
||||||
const necessaryAttrs: string[] = ['id', '$$createAt$$']; // 有的页面依赖于其它页面取数据,有时两个页面的filter的差异会导致有一个加createAt,有一个不加,此时可能产生前台取数据不完整的异常。先统一加上
|
|
||||||
for (const attr in projectionNode) {
|
|
||||||
if (attr === '#id') {
|
|
||||||
assert(!projectionNodeDict[projectionNode[attr]!], `projection中结点的id有重复, ${projectionNode[attr]}`);
|
|
||||||
Object.assign(projectionNodeDict, {
|
|
||||||
[projectionNode[attr]!]: projectionNode,
|
|
||||||
});
|
|
||||||
if (toBeAssignNode2[projectionNode[attr]!]) {
|
|
||||||
checkNode(projectionNode, toBeAssignNode2[projectionNode[attr]!]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (attr.toLowerCase().startsWith(EXPRESSION_PREFIX)) {
|
|
||||||
const exprResult = getAttrRefInExpression(projectionNode[attr]!);
|
|
||||||
for (const nodeName in exprResult) {
|
|
||||||
if (nodeName === '#current') {
|
|
||||||
checkNode(projectionNode, exprResult[nodeName]);
|
|
||||||
}
|
|
||||||
else if (projectionNodeDict[nodeName]) {
|
|
||||||
checkNode(projectionNodeDict[nodeName], exprResult[nodeName]);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (toBeAssignNode2[nodeName]) {
|
|
||||||
toBeAssignNode2[nodeName].push(...exprResult[nodeName]);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Object.assign(toBeAssignNode2, {
|
|
||||||
[nodeName]: exprResult[nodeName],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
const rel = judgeRelation(schema, entity2, attr);
|
|
||||||
if (rel === 1) {
|
|
||||||
necessaryAttrs.push(attr);
|
|
||||||
}
|
|
||||||
else if (rel === 2) {
|
|
||||||
// entity/entityId反指
|
|
||||||
necessaryAttrs.push('entity', 'entityId');
|
|
||||||
checkProjectionNode(attr, projectionNode[attr]);
|
|
||||||
}
|
|
||||||
else if (typeof rel === 'string') {
|
|
||||||
necessaryAttrs.push(`${attr}Id`);
|
|
||||||
checkProjectionNode(rel, projectionNode[attr]);
|
|
||||||
}
|
|
||||||
else if (rel instanceof Array && !attr.endsWith('$$aggr')) {
|
|
||||||
const { data } = projectionNode[attr];
|
|
||||||
if (rel[1]) {
|
|
||||||
checkNode(data, [rel[1]]);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
checkNode(data, ['entity', 'entityId']);
|
|
||||||
}
|
|
||||||
reinforceSelection(schema, rel[0], projectionNode[attr]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
checkNode(projectionNode, necessaryAttrs);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果对象中指向一对多的Modi,此时加上指向Modi的projection
|
|
||||||
if (schema[entity2].toModi) {
|
|
||||||
Object.assign(projectionNode, {
|
|
||||||
modi$entity: {
|
|
||||||
$entity: 'modi',
|
|
||||||
data: {
|
|
||||||
id: 1,
|
|
||||||
targetEntity: 1,
|
|
||||||
entity: 1,
|
|
||||||
entityId: 1,
|
|
||||||
action: 1,
|
|
||||||
iState: 1,
|
|
||||||
data: 1,
|
|
||||||
filter: 1,
|
|
||||||
},
|
|
||||||
filter: {
|
|
||||||
iState: 'active',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
checkProjectionNode(entity, data);
|
|
||||||
|
|
||||||
if (!sorter && relevantIds.length === 0) {
|
|
||||||
// 如果没有sorter,就给予一个按createAt逆序的sorter
|
|
||||||
Object.assign(selection, {
|
|
||||||
sorter: [
|
|
||||||
{
|
|
||||||
$attr: {
|
|
||||||
$$createAt$$: 1,
|
|
||||||
},
|
|
||||||
$direction: 'desc',
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
Object.assign(data, {
|
|
||||||
$$createAt$$: 1,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
SelectionRewriters.forEach(
|
|
||||||
ele => ele(schema, entity, selection)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 对operation进行一些完善,作为operation算子的注入点
|
|
||||||
* @param schema
|
|
||||||
* @param entity
|
|
||||||
* @param selection
|
|
||||||
*/
|
|
||||||
export function reinforceOperation<ED extends EntityDict>(schema: StorageSchema<ED>, entity: keyof ED, operation: ED[keyof ED]['Operation']) {
|
|
||||||
OperationRewriters.forEach(
|
|
||||||
ele => ele(schema, entity, operation)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
import { EntityDict } from '../types/Entity';
|
||||||
|
import { EntityDict as BaseEntityDict } from '../base-app-domain';
|
||||||
|
import { AsyncContext } from '../store/AsyncRowStore';
|
||||||
|
import { vaccumEntities } from './vaccum';
|
||||||
|
import { combineFilters } from '../store/filter';
|
||||||
|
|
||||||
|
export type VaccumOperOption<ED extends EntityDict & BaseEntityDict> = {
|
||||||
|
aliveLine: number;
|
||||||
|
excludeOpers?: {
|
||||||
|
[T in keyof ED]?: ED[T]['Action'][];
|
||||||
|
};
|
||||||
|
backupDir?: string;
|
||||||
|
zip?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将一定日期之前的oper对象清空
|
||||||
|
* @param option
|
||||||
|
* @param context
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export async function vaccumOper<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED>>(option: VaccumOperOption<ED>, context: Cxt) {
|
||||||
|
const { aliveLine, excludeOpers, ...rest } = option;
|
||||||
|
|
||||||
|
const operFilter: ED['oper']['Selection']['filter'] = {};
|
||||||
|
if (excludeOpers) {
|
||||||
|
const notFilters: ED['oper']['Selection']['filter'][] = [];
|
||||||
|
for (const key in excludeOpers) {
|
||||||
|
if (excludeOpers[key]!.length > 0) {
|
||||||
|
notFilters.push({
|
||||||
|
targetEntity: key,
|
||||||
|
action: {
|
||||||
|
$in: excludeOpers[key],
|
||||||
|
}
|
||||||
|
} as ED['oper']['Selection']['filter']);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
notFilters.push({
|
||||||
|
targetEntity: key,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (notFilters.length > 0) {
|
||||||
|
operFilter.$not = {
|
||||||
|
$or: notFilters as NonNullable<ED['oper']['Selection']['filter']>[],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return vaccumEntities({
|
||||||
|
entities: [{
|
||||||
|
entity: 'operEntity',
|
||||||
|
aliveLine: aliveLine + 10000,
|
||||||
|
filter: {
|
||||||
|
oper: combineFilters([operFilter, {
|
||||||
|
$$createAt$$: {
|
||||||
|
$lt: aliveLine,
|
||||||
|
}
|
||||||
|
}]),
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
entity: 'oper',
|
||||||
|
aliveLine,
|
||||||
|
filter: operFilter,
|
||||||
|
}],
|
||||||
|
...rest,
|
||||||
|
}, context);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,134 @@
|
||||||
|
import dayJs from 'dayjs';
|
||||||
|
import { appendFileSync, existsSync, openSync, rmSync, closeSync, createReadStream, createWriteStream } from 'fs';
|
||||||
|
import { EntityDict } from '../types/Entity';
|
||||||
|
import { EntityDict as BaseEntityDict } from '../base-app-domain';
|
||||||
|
import { AsyncContext } from '../store/AsyncRowStore';
|
||||||
|
import { combineFilters } from '../store/filter';
|
||||||
|
import { createGzip } from 'node:zlib';
|
||||||
|
import { pipeline } from 'stream';
|
||||||
|
import { generateNewIdAsync } from '../utils/uuid';
|
||||||
|
|
||||||
|
type VaccumOptionEntity<ED extends EntityDict & BaseEntityDict, T extends keyof ED> = {
|
||||||
|
entity: T;
|
||||||
|
filter?: ED[T]['Selection']['filter']; // 如果有额外的条件,放在filter中(满足条件的才会被清空)
|
||||||
|
aliveLine: number; // vaccum一定是按createAt清空数据,在aliveLine之后的数据不会被清空
|
||||||
|
};
|
||||||
|
|
||||||
|
type VaccumOption<ED extends EntityDict & BaseEntityDict> = {
|
||||||
|
entities: Array<VaccumOptionEntity<ED, keyof ED>>;
|
||||||
|
backupDir?: string;
|
||||||
|
zip?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除数据库中的部分数据,减少体积
|
||||||
|
* 一般只删除日志类数据
|
||||||
|
* @param option
|
||||||
|
*/
|
||||||
|
export async function vaccumEntities<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED>>(option: VaccumOption<ED>, context: Cxt) {
|
||||||
|
const { entities, backupDir } = option;
|
||||||
|
for (const ele of entities) {
|
||||||
|
const { entity, filter, aliveLine } = ele;
|
||||||
|
|
||||||
|
let filter2: ED[keyof ED]['Selection']['filter'] = {
|
||||||
|
$$createAt$$: {
|
||||||
|
$lt: aliveLine,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
if (filter) {
|
||||||
|
filter2 = combineFilters([filter2, filter]);
|
||||||
|
}
|
||||||
|
if (backupDir) {
|
||||||
|
// 使用mysqldump将待删除的数据备份出来
|
||||||
|
const { zip: zip } = option;
|
||||||
|
const now = dayJs();
|
||||||
|
const backFile = `${backupDir}/${entity as string}-${now.format('YYYY-MM-DD HH:mm:ss')}.csv`;
|
||||||
|
if (existsSync(backFile)) {
|
||||||
|
rmSync(backFile);
|
||||||
|
}
|
||||||
|
const fd = openSync(backFile, 'a');
|
||||||
|
const attributes = ['id', '$$createAt$$', '$$updateAt$$', '$$deleteAt$$'];
|
||||||
|
const projection: ED[keyof ED]['Selection']['data']= {
|
||||||
|
id: 1,
|
||||||
|
$$createAt$$: 1,
|
||||||
|
$$updateAt$$: 1,
|
||||||
|
$$deleteAt$$: 1,
|
||||||
|
};
|
||||||
|
for (const attr in context.getSchema()[entity]!.attributes) {
|
||||||
|
Object.assign(projection, {
|
||||||
|
[attr]: 1,
|
||||||
|
});
|
||||||
|
attributes.push(attr);
|
||||||
|
}
|
||||||
|
appendFileSync(fd, attributes.join(','));
|
||||||
|
appendFileSync(fd, '\n');
|
||||||
|
|
||||||
|
|
||||||
|
let count = 0;
|
||||||
|
const appendData = async (minCreateAt: number): Promise<void> => {
|
||||||
|
const filter3 = combineFilters([filter2, {
|
||||||
|
$$createAt$$: {
|
||||||
|
$gt: minCreateAt,
|
||||||
|
},
|
||||||
|
}]);
|
||||||
|
const rows = await context.select(entity, {
|
||||||
|
data: projection,
|
||||||
|
filter: filter3,
|
||||||
|
sorter: [{
|
||||||
|
$attr: {
|
||||||
|
$$createAt$$: 1,
|
||||||
|
},
|
||||||
|
$direction: 'asc'
|
||||||
|
}],
|
||||||
|
indexFrom: 0,
|
||||||
|
count: 1000,
|
||||||
|
}, { includedDeleted: true });
|
||||||
|
const csvTxt = rows.map(
|
||||||
|
(row) => attributes.map(
|
||||||
|
(attr) => JSON.stringify(row[attr])
|
||||||
|
).join(',')
|
||||||
|
).join('\n');
|
||||||
|
appendFileSync(fd, csvTxt);
|
||||||
|
appendFileSync(fd, '\n');
|
||||||
|
count += rows.length;
|
||||||
|
if (rows.length === 1000) {
|
||||||
|
const maxCreateAt = rows[999].$$createAt$$;
|
||||||
|
return appendData(maxCreateAt as number);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
await appendData(0);
|
||||||
|
closeSync(fd);
|
||||||
|
console.log(`备份${entity as string}对象完毕,共备份了${count}行数据`);
|
||||||
|
|
||||||
|
if (count === 0) {
|
||||||
|
rmSync(backFile);
|
||||||
|
}
|
||||||
|
else if (zip) {
|
||||||
|
const gzip = createGzip();
|
||||||
|
const source = createReadStream(backFile);
|
||||||
|
const destination = createWriteStream(`${backFile}.zip`);
|
||||||
|
await new Promise(
|
||||||
|
(resolve, reject) => {
|
||||||
|
pipeline(source, gzip, destination, (err) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
resolve(undefined);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将对应的数据删除
|
||||||
|
await context.operate(entity, {
|
||||||
|
id: await generateNewIdAsync(),
|
||||||
|
action: 'remove',
|
||||||
|
data: {},
|
||||||
|
filter: filter2,
|
||||||
|
}, { deletePhysically: true });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -16,10 +16,10 @@ export abstract class Connector<ED extends EntityDict, BackCxt extends AsyncCont
|
||||||
|
|
||||||
abstract parseRequest(headers: IncomingHttpHeaders, body: any, store: AsyncRowStore<ED, BackCxt>): Promise<{ name: string; params: any; context: BackCxt; }>;
|
abstract parseRequest(headers: IncomingHttpHeaders, body: any, store: AsyncRowStore<ED, BackCxt>): Promise<{ name: string; params: any; context: BackCxt; }>;
|
||||||
|
|
||||||
abstract serializeResult(result: any, context: BackCxt, headers: IncomingHttpHeaders, body: any): {
|
abstract serializeResult(result: any, context: BackCxt, headers: IncomingHttpHeaders, body: any): Promise<{
|
||||||
body: any;
|
body: any;
|
||||||
headers?: Record<string, any>;
|
headers?: Record<string, any>;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
abstract serializeException(exception: OakException<ED>, headers: IncomingHttpHeaders, body: any): {
|
abstract serializeException(exception: OakException<ED>, headers: IncomingHttpHeaders, body: any): {
|
||||||
body: any;
|
body: any;
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ export type OperateOption = {
|
||||||
allowExists?: boolean; // 插入时允许已经存在唯一键值的行了,即insert / update逻辑
|
allowExists?: boolean; // 插入时允许已经存在唯一键值的行了,即insert / update逻辑
|
||||||
modiParentId?: string; // 如果是延时更新,相关modi要关联到一个父亲上统一应用
|
modiParentId?: string; // 如果是延时更新,相关modi要关联到一个父亲上统一应用
|
||||||
modiParentEntity?: string; // 如果是延时更新,相关modi要关联到一个父亲上统一应用
|
modiParentEntity?: string; // 如果是延时更新,相关modi要关联到一个父亲上统一应用
|
||||||
|
deletePhysically?: boolean;
|
||||||
dummy?: 1; // 无用,为了继承Option通过编译
|
dummy?: 1; // 无用,为了继承Option通过编译
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,10 @@ export type TxnOption = {
|
||||||
isolationLevel: 'repeatable read' | 'serializable';
|
isolationLevel: 'repeatable read' | 'serializable';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type SelectionRewriter<ED extends EntityDict> = (schema: StorageSchema<ED>, entity: keyof ED, selection: ED[keyof ED]['Selection']) => void;
|
||||||
|
export type OperationRewriter<ED extends EntityDict> = (schema: StorageSchema<ED>, entity: keyof ED, operate: ED[keyof ED]['Operation']) => void;
|
||||||
|
|
||||||
|
|
||||||
export abstract class RowStore<ED extends EntityDict> {
|
export abstract class RowStore<ED extends EntityDict> {
|
||||||
protected storageSchema: StorageSchema<ED>;
|
protected storageSchema: StorageSchema<ED>;
|
||||||
|
|
||||||
|
|
@ -13,6 +17,10 @@ export abstract class RowStore<ED extends EntityDict> {
|
||||||
this.storageSchema = storageSchema;
|
this.storageSchema = storageSchema;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract registerOperationRewriter(rewriter: OperationRewriter<ED>): void;
|
||||||
|
|
||||||
|
abstract registerSelectionRewriter(rewriter: SelectionRewriter<ED>): void;
|
||||||
|
|
||||||
getSchema () {
|
getSchema () {
|
||||||
return this.storageSchema;
|
return this.storageSchema;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -104,12 +104,14 @@ export class SimpleConnector<ED extends EntityDict, BackCxt extends AsyncContext
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
serializeResult(result: any, context: BackCxt, headers: IncomingHttpHeaders, body: any): { body: any; headers?: Record<string, any> | undefined; } {
|
async serializeResult(result: any, context: BackCxt, headers: IncomingHttpHeaders, body: any): Promise<{ body: any; headers?: Record<string, any> | undefined; }> {
|
||||||
if (result instanceof Stream || result instanceof Buffer) {
|
if (result instanceof Stream || result instanceof Buffer) {
|
||||||
return {
|
return {
|
||||||
body: result,
|
body: result,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await context.refineOpRecords();
|
||||||
return {
|
return {
|
||||||
body: {
|
body: {
|
||||||
result,
|
result,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue