modi相关的checkers以及schema中actionType的细化
This commit is contained in:
parent
87b30fb8fa
commit
51b4600147
|
|
@ -1,5 +1,11 @@
|
|||
import { ActionDef } from '../types/Action';
|
||||
export declare type GenericAction = 'create' | 'update' | 'remove' | 'select' | 'count' | 'stat' | 'download';
|
||||
export declare type ReadOnlyAction = 'select' | 'count' | 'stat' | 'download';
|
||||
export declare type AppendOnlyAction = ReadOnlyAction | 'create';
|
||||
export declare type ExcludeUpdateAction = AppendOnlyAction | 'remove';
|
||||
export declare type GenericAction = 'update' | ExcludeUpdateAction;
|
||||
export declare const readOnlyActions: string[];
|
||||
export declare const appendOnlyActions: string[];
|
||||
export declare const excludeUpdateActions: string[];
|
||||
export declare const genericActions: string[];
|
||||
export declare type AbleAction = 'enable' | 'disable';
|
||||
export declare type AbleState = 'enabled' | 'disabled';
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.makeAbleActionDef = exports.genericActions = void 0;
|
||||
exports.genericActions = ['create', 'update', 'remove', 'count', 'stat', 'download', 'select'];
|
||||
exports.makeAbleActionDef = exports.genericActions = exports.excludeUpdateActions = exports.appendOnlyActions = exports.readOnlyActions = void 0;
|
||||
exports.readOnlyActions = ['count', 'stat', 'download', 'select'];
|
||||
exports.appendOnlyActions = exports.readOnlyActions.concat('create');
|
||||
exports.excludeUpdateActions = exports.appendOnlyActions.concat('remove');
|
||||
exports.genericActions = exports.excludeUpdateActions.concat('update');
|
||||
var makeAbleActionDef = function (initialState) { return ({
|
||||
stm: {
|
||||
enable: ['disabled', 'enabled'],
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ export declare type IState = 'active' | 'applied' | 'abandoned';
|
|||
export declare type IAction = 'apply' | 'abandon';
|
||||
export declare type ParticularAction = IAction;
|
||||
export declare type Action = GenericAction | ParticularAction;
|
||||
export declare const actions: string[];
|
||||
export declare const ActionDefDict: {
|
||||
iState: ActionDef<IAction, IState>;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.ActionDefDict = void 0;
|
||||
exports.ActionDefDict = exports.actions = void 0;
|
||||
var IActionDef = {
|
||||
stm: {
|
||||
apply: ['active', 'applied'],
|
||||
|
|
@ -8,6 +8,7 @@ var IActionDef = {
|
|||
},
|
||||
is: 'active'
|
||||
};
|
||||
exports.actions = ["count", "stat", "download", "select", "create", "remove", "update", "apply", "abandon"];
|
||||
exports.ActionDefDict = {
|
||||
iState: IActionDef
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.desc = void 0;
|
||||
var Action_1 = require("./Action");
|
||||
exports.desc = {
|
||||
attributes: {
|
||||
targetEntity: {
|
||||
|
|
@ -43,6 +44,8 @@ exports.desc = {
|
|||
}
|
||||
}
|
||||
},
|
||||
actionType: "crud",
|
||||
actions: Action_1.actions,
|
||||
indexes: [
|
||||
{
|
||||
name: 'index_state',
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.desc = void 0;
|
||||
var action_1 = require("../../actions/action");
|
||||
exports.desc = {
|
||||
attributes: {
|
||||
modiId: {
|
||||
|
|
@ -19,5 +20,7 @@ exports.desc = {
|
|||
length: 64
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
actionType: "appendOnly",
|
||||
actions: action_1.appendOnlyActions
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.desc = void 0;
|
||||
var action_1 = require("../../actions/action");
|
||||
exports.desc = {
|
||||
attributes: {
|
||||
action: {
|
||||
|
|
@ -22,5 +23,7 @@ exports.desc = {
|
|||
type: "ref",
|
||||
ref: "user"
|
||||
}
|
||||
}
|
||||
},
|
||||
actionType: "appendOnly",
|
||||
actions: action_1.appendOnlyActions
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.desc = void 0;
|
||||
var action_1 = require("../../actions/action");
|
||||
exports.desc = {
|
||||
attributes: {
|
||||
operId: {
|
||||
|
|
@ -19,5 +20,7 @@ exports.desc = {
|
|||
length: 64
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
actionType: "appendOnly",
|
||||
actions: action_1.appendOnlyActions
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.desc = void 0;
|
||||
var action_1 = require("../../actions/action");
|
||||
exports.desc = {
|
||||
attributes: {
|
||||
name: {
|
||||
|
|
@ -18,5 +19,7 @@ exports.desc = {
|
|||
password: {
|
||||
type: "text"
|
||||
}
|
||||
}
|
||||
},
|
||||
actionType: "crud",
|
||||
actions: action_1.genericActions
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
import { EntityDict } from '../base-app-domain';
|
||||
import { StorageSchema, EntityDict as BaseEntityDict, Context } from '../types';
|
||||
export declare function createCheckers<ED extends EntityDict & BaseEntityDict, Cxt extends Context<ED>>(schema: StorageSchema<ED>): import("../types").Checker<ED, keyof ED, Cxt>[];
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createCheckers = void 0;
|
||||
var modi_1 = require("../store/modi");
|
||||
function createCheckers(schema) {
|
||||
return (0, modi_1.createModiRelatedCheckers)(schema);
|
||||
}
|
||||
exports.createCheckers = createCheckers;
|
||||
|
|
@ -199,7 +199,7 @@ var RESERVED_ACTION_NAMES = ['GenericAction', 'ParticularAction'];
|
|||
var action_1 = require("../actions/action");
|
||||
var DataType_1 = require("../types/DataType");
|
||||
var Entity_1 = require("../types/Entity");
|
||||
function dealWithActions(moduleName, filename, node, program) {
|
||||
function dealWithActions(moduleName, filename, node, program, sourceFile) {
|
||||
var actionTexts = action_1.genericActions.map(function (ele) { return ele; });
|
||||
if (ts.isUnionTypeNode(node)) {
|
||||
var actionNames = node.types.map(function (ele) {
|
||||
|
|
@ -243,8 +243,7 @@ function dealWithActions(moduleName, filename, node, program) {
|
|||
_a));
|
||||
}
|
||||
});
|
||||
// 为每个action在schema中建立相应的state域(除了genericState)
|
||||
// 放到actionDef的定义处去做。by Xc
|
||||
pushStatementIntoActionAst(moduleName, factory.createVariableStatement([factory.createModifier(ts.SyntaxKind.ExportKeyword)], factory.createVariableDeclarationList([factory.createVariableDeclaration(factory.createIdentifier("actions"), undefined, undefined, factory.createArrayLiteralExpression(actionTexts.map(function (ele) { return factory.createStringLiteral(ele); }), false))], ts.NodeFlags.Const)), sourceFile);
|
||||
}
|
||||
function getEntityImported(declaration, filename) {
|
||||
var moduleSpecifier = declaration.moduleSpecifier, importClause = declaration.importClause;
|
||||
|
|
@ -315,6 +314,7 @@ function analyzeEntity(filename, path, program) {
|
|||
var hasRelationDef = false;
|
||||
var hasActionOrStateDef = false;
|
||||
var toModi = false;
|
||||
var actionType = 'crud';
|
||||
var enumStringAttrs = [];
|
||||
var states = [];
|
||||
var localEnumStringTypes = [];
|
||||
|
|
@ -484,7 +484,7 @@ function analyzeEntity(filename, path, program) {
|
|||
factory.createTypeReferenceNode(factory.createIdentifier("GenericAction"), undefined),
|
||||
factory.createTypeReferenceNode(factory.createIdentifier("ParticularAction"), undefined)
|
||||
])), sourceFile);
|
||||
dealWithActions(moduleName, filename, node.type, program);
|
||||
dealWithActions(moduleName, filename, node.type, program, sourceFile);
|
||||
}
|
||||
else if (node.name.text === 'Relation') {
|
||||
(0, assert_1.default)(!localeDef, "\u3010".concat(filename, "\u3011locale\u5B9A\u4E49\u987B\u5728Relation\u4E4B\u540E"));
|
||||
|
|
@ -688,11 +688,10 @@ function analyzeEntity(filename, path, program) {
|
|||
});
|
||||
indexes = declaration.initializer;
|
||||
}
|
||||
else if (ts.isIdentifier(declaration.name) && declaration.name.text === 'locale') {
|
||||
else if (ts.isTypeReferenceNode(declaration.type) && ts.isIdentifier(declaration.type.typeName) && declaration.type.typeName.text === 'LocaleDef') {
|
||||
// locale定义
|
||||
var type = declaration.type, initializer = declaration.initializer;
|
||||
(0, assert_1.default)(ts.isObjectLiteralExpression(initializer));
|
||||
(0, assert_1.default)(ts.isTypeReferenceNode(type) && ts.isIdentifier(type.typeName) && type.typeName.text === 'LocaleDef', 'locale定义的类型必须是LocaleDef');
|
||||
var properties = initializer.properties;
|
||||
(0, assert_1.default)(properties.length > 0, "".concat(filename, "\u81F3\u5C11\u9700\u8981\u6709\u4E00\u79CDlocale\u5B9A\u4E49"));
|
||||
var allEnumStringAttrs = enumStringAttrs.concat(states);
|
||||
|
|
@ -737,6 +736,10 @@ function analyzeEntity(filename, path, program) {
|
|||
}
|
||||
localeDef = initializer;
|
||||
}
|
||||
else if (ts.isTypeReferenceNode(declaration.type) && ts.isIdentifier(declaration.type.typeName) && declaration.type.typeName.text === 'ActionType') {
|
||||
(0, assert_1.default)(ts.isStringLiteral(declaration.initializer));
|
||||
actionType = declaration.initializer.text;
|
||||
}
|
||||
else {
|
||||
throw new Error("\u4E0D\u80FD\u7406\u89E3\u7684\u5B9A\u4E49\u5185\u5BB9".concat(declaration.name.getText()));
|
||||
}
|
||||
|
|
@ -746,11 +749,15 @@ function analyzeEntity(filename, path, program) {
|
|||
if (!hasActionDef && hasActionOrStateDef) {
|
||||
throw new Error("".concat(filename, "\u4E2D\u6709Action\u6216State\u5B9A\u4E49\uFF0C\u4F46\u6CA1\u6709\u5B9A\u4E49\u5B8C\u6574\u7684Action\u7C7B\u578B"));
|
||||
}
|
||||
if (hasActionDef && actionType !== 'crud') {
|
||||
throw new Error("".concat(filename, "\u4E2D\u6709Action\u5B9A\u4E49\uFF0C\u4F46\u5374\u5B9A\u4E49\u4E86actionType\u4E0D\u662Fcrud"));
|
||||
}
|
||||
(0, assert_1.default)(schemaAttrs.length > 0);
|
||||
var schema = {
|
||||
schemaAttrs: schemaAttrs,
|
||||
sourceFile: sourceFile,
|
||||
toModi: toModi,
|
||||
actionType: actionType,
|
||||
};
|
||||
if (hasFulltextIndex) {
|
||||
(0, lodash_1.assign)(schema, {
|
||||
|
|
@ -2639,11 +2646,33 @@ function outputStorage(outputDir, printer) {
|
|||
var entityAssignments = [];
|
||||
for (var entity in Schema) {
|
||||
var indexExpressions = [];
|
||||
var _a = Schema[entity], sourceFile = _a.sourceFile, fulltextIndex = _a.fulltextIndex, indexes = _a.indexes, toModi = _a.toModi;
|
||||
var _a = Schema[entity], sourceFile = _a.sourceFile, fulltextIndex = _a.fulltextIndex, indexes = _a.indexes, toModi = _a.toModi, actionType = _a.actionType;
|
||||
var statements = [
|
||||
factory.createImportDeclaration(undefined, undefined, factory.createImportClause(false, undefined, factory.createNamedImports([factory.createImportSpecifier(false, undefined, factory.createIdentifier("StorageDesc"))])), factory.createStringLiteral("".concat((0, env_1.TYPE_PATH_IN_OAK_DOMAIN)(), "Storage")), undefined),
|
||||
factory.createImportDeclaration(undefined, undefined, factory.createImportClause(false, undefined, factory.createNamedImports([factory.createImportSpecifier(false, undefined, factory.createIdentifier("OpSchema"))])), factory.createStringLiteral("./Schema"), undefined)
|
||||
];
|
||||
switch (actionType) {
|
||||
case 'readOnly': {
|
||||
statements.push(factory.createImportDeclaration(undefined, undefined, factory.createImportClause(false, undefined, factory.createNamedImports([factory.createImportSpecifier(false, factory.createIdentifier("readOnlyActions"), factory.createIdentifier("actions"))])), factory.createStringLiteral((0, env_1.ACTION_CONSTANT_IN_OAK_DOMAIN)()), undefined));
|
||||
break;
|
||||
}
|
||||
case 'appendOnly': {
|
||||
statements.push(factory.createImportDeclaration(undefined, undefined, factory.createImportClause(false, undefined, factory.createNamedImports([factory.createImportSpecifier(false, factory.createIdentifier("appendOnlyActions"), factory.createIdentifier("actions"))])), factory.createStringLiteral((0, env_1.ACTION_CONSTANT_IN_OAK_DOMAIN)()), undefined));
|
||||
break;
|
||||
}
|
||||
case 'excludeUpdate': {
|
||||
statements.push(factory.createImportDeclaration(undefined, undefined, factory.createImportClause(false, undefined, factory.createNamedImports([factory.createImportSpecifier(false, factory.createIdentifier("excludeUpdateActions"), factory.createIdentifier("actions"))])), factory.createStringLiteral((0, env_1.ACTION_CONSTANT_IN_OAK_DOMAIN)()), undefined));
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if (ActionAsts[entity]) {
|
||||
statements.push(factory.createImportDeclaration(undefined, undefined, factory.createImportClause(false, undefined, factory.createNamedImports([factory.createImportSpecifier(false, undefined, factory.createIdentifier("actions"))])), factory.createStringLiteral("./Action"), undefined));
|
||||
}
|
||||
else {
|
||||
statements.push(factory.createImportDeclaration(undefined, undefined, factory.createImportClause(false, undefined, factory.createNamedImports([factory.createImportSpecifier(false, factory.createIdentifier("genericActions"), factory.createIdentifier("actions"))])), factory.createStringLiteral((0, env_1.ACTION_CONSTANT_IN_OAK_DOMAIN)()), undefined));
|
||||
}
|
||||
}
|
||||
}
|
||||
var propertyAssignments = [];
|
||||
var attributes = constructAttributes(entity);
|
||||
propertyAssignments.push(factory.createPropertyAssignment(factory.createIdentifier("attributes"), factory.createObjectLiteralExpression(attributes, true)));
|
||||
|
|
@ -2653,6 +2682,7 @@ function outputStorage(outputDir, printer) {
|
|||
if (toModi) {
|
||||
propertyAssignments.push(factory.createPropertyAssignment(factory.createIdentifier("toModi"), factory.createTrue()));
|
||||
}
|
||||
propertyAssignments.push(factory.createPropertyAssignment(factory.createIdentifier("actionType"), factory.createStringLiteral(actionType)), factory.createShorthandPropertyAssignment(factory.createIdentifier("actions"), undefined));
|
||||
if (indexExpressions.length > 0) {
|
||||
propertyAssignments.push(factory.createPropertyAssignment(factory.createIdentifier("indexes"), factory.createArrayLiteralExpression(indexExpressions, true)));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
;
|
||||
var actionType = 'appendOnly';
|
||||
var locale = {
|
||||
zh_CN: {
|
||||
attr: {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
;
|
||||
var actionType = 'appendOnly';
|
||||
var locale = {
|
||||
zh_CN: {
|
||||
attr: {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
;
|
||||
var actionType = 'appendOnly';
|
||||
var locale = {
|
||||
zh_CN: {
|
||||
attr: {
|
||||
|
|
|
|||
|
|
@ -723,7 +723,7 @@ var CascadeStore = /** @class */ (function (_super) {
|
|||
}
|
||||
return [3 /*break*/, 23];
|
||||
case 1:
|
||||
if (!(option.modiParentEntity && !['modi', 'modiEntity'].includes(entity))) return [3 /*break*/, 3];
|
||||
if (!(option.modiParentEntity && !['modi', 'modiEntity', 'oper', 'operEntity'].includes(entity))) return [3 /*break*/, 3];
|
||||
modiCreate = {
|
||||
id: 'dummy',
|
||||
action: 'create',
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
import { OpSchema as Modi } from '../base-app-domain/Modi/Schema';
|
||||
import { Operation } from '../types';
|
||||
import { EntityDict } from '../base-app-domain';
|
||||
import { UniversalContext } from '../store/UniversalContext';
|
||||
import { OpSchema as Modi, Filter } from '../base-app-domain/Modi/Schema';
|
||||
import { Checker, Operation, StorageSchema, EntityDict as BaseEntityDict, Context } from '../types';
|
||||
export declare function createOperationsFromModies(modies: Modi[]): Array<{
|
||||
operation: Operation<string, Object, Object>;
|
||||
entity: string;
|
||||
}>;
|
||||
export declare function applyModis<ED extends EntityDict, Cxt extends UniversalContext<ED>>(filter: Filter, context: Cxt): Promise<import("../types").OperationResult<ED>>;
|
||||
export declare function abandonModis<ED extends EntityDict, Cxt extends UniversalContext<ED>>(filter: Filter, context: Cxt): Promise<import("../types").OperationResult<ED>>;
|
||||
export declare function createModiRelatedCheckers<ED extends EntityDict & BaseEntityDict, Cxt extends Context<ED>>(schema: StorageSchema<ED>): Checker<ED, keyof ED, Cxt>[];
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createOperationsFromModies = void 0;
|
||||
exports.createModiRelatedCheckers = exports.abandonModis = exports.applyModis = exports.createOperationsFromModies = void 0;
|
||||
var tslib_1 = require("tslib");
|
||||
var types_1 = require("../types");
|
||||
var action_1 = require("../actions/action");
|
||||
var lodash_1 = require("../utils/lodash");
|
||||
function createOperationsFromModies(modies) {
|
||||
return modies.map(function (modi) {
|
||||
return {
|
||||
|
|
@ -15,3 +19,125 @@ function createOperationsFromModies(modies) {
|
|||
});
|
||||
}
|
||||
exports.createOperationsFromModies = createOperationsFromModies;
|
||||
function applyModis(filter, context) {
|
||||
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
||||
var _a, _b, _c;
|
||||
var _d;
|
||||
return tslib_1.__generator(this, function (_e) {
|
||||
switch (_e.label) {
|
||||
case 0:
|
||||
_b = (_a = context.rowStore).operate;
|
||||
_c = ['modi'];
|
||||
_d = {};
|
||||
return [4 /*yield*/, generateNewId()];
|
||||
case 1: return [2 /*return*/, _b.apply(_a, _c.concat([(_d.id = _e.sent(),
|
||||
_d.action = 'apply',
|
||||
_d.data = {},
|
||||
_d.filter = filter,
|
||||
_d.sorter = [
|
||||
{
|
||||
$attr: {
|
||||
$$createAt$$: 1,
|
||||
},
|
||||
$direction: 'asc',
|
||||
}
|
||||
],
|
||||
_d), context, {
|
||||
dontCollect: true,
|
||||
blockTrigger: true,
|
||||
}]))];
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
exports.applyModis = applyModis;
|
||||
function abandonModis(filter, context) {
|
||||
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
||||
var _a, _b, _c;
|
||||
var _d;
|
||||
return tslib_1.__generator(this, function (_e) {
|
||||
switch (_e.label) {
|
||||
case 0:
|
||||
_b = (_a = context.rowStore).operate;
|
||||
_c = ['modi'];
|
||||
_d = {};
|
||||
return [4 /*yield*/, generateNewId()];
|
||||
case 1: return [2 /*return*/, _b.apply(_a, _c.concat([(_d.id = _e.sent(),
|
||||
_d.action = 'abadon',
|
||||
_d.data = {},
|
||||
_d.filter = filter,
|
||||
_d.sorter = [
|
||||
{
|
||||
$attr: {
|
||||
$$createAt$$: 1,
|
||||
},
|
||||
$direction: 'asc',
|
||||
}
|
||||
],
|
||||
_d), context, {
|
||||
dontCollect: true,
|
||||
blockTrigger: true,
|
||||
}]))];
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
exports.abandonModis = abandonModis;
|
||||
function createModiRelatedCheckers(schema) {
|
||||
var _this = this;
|
||||
var checkers = [];
|
||||
var _loop_1 = function (entity) {
|
||||
var _a = schema[entity], actionType = _a.actionType, actions = _a.actions;
|
||||
if (['modi', 'modiEntity', 'oper', 'operEntity'].includes(entity) || ['readOnly', 'appendOnly'].includes(actionType)) {
|
||||
return "continue";
|
||||
}
|
||||
var restActions = (0, lodash_1.difference)(actions, action_1.appendOnlyActions);
|
||||
checkers.push({
|
||||
entity: entity,
|
||||
action: restActions,
|
||||
type: 'row',
|
||||
checker: function (_a, context) {
|
||||
var operation = _a.operation;
|
||||
return tslib_1.__awaiter(_this, void 0, void 0, function () {
|
||||
var filter, filter2, count;
|
||||
var _b;
|
||||
return tslib_1.__generator(this, function (_c) {
|
||||
switch (_c.label) {
|
||||
case 0:
|
||||
filter = operation.filter;
|
||||
filter2 = {
|
||||
modi: {
|
||||
iState: 'active',
|
||||
},
|
||||
};
|
||||
if (filter) {
|
||||
Object.assign(filter2, (_b = {},
|
||||
_b[entity] = filter,
|
||||
_b));
|
||||
}
|
||||
else {
|
||||
Object.assign(filter2, {
|
||||
entity: entity,
|
||||
});
|
||||
}
|
||||
return [4 /*yield*/, context.rowStore.count('modiEntity', {
|
||||
filter: filter2,
|
||||
}, context, {})];
|
||||
case 1:
|
||||
count = _c.sent();
|
||||
if (count > 0) {
|
||||
throw new types_1.OakRowLockedException();
|
||||
}
|
||||
return [2 /*return*/, 0];
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
||||
for (var entity in schema) {
|
||||
_loop_1(entity);
|
||||
}
|
||||
return checkers;
|
||||
}
|
||||
exports.createModiRelatedCheckers = createModiRelatedCheckers;
|
||||
|
|
|
|||
|
|
@ -42,7 +42,9 @@ var triggers = [
|
|||
action: action,
|
||||
data: data,
|
||||
filter: filter_1,
|
||||
}, context, option)];
|
||||
}, context, Object.assign({}, option, {
|
||||
blockTrigger: true,
|
||||
}))];
|
||||
case 4:
|
||||
_c.sent();
|
||||
_c.label = 5;
|
||||
|
|
|
|||
|
|
@ -13,13 +13,14 @@ export declare type Filter<A extends string, F extends Object | undefined = unde
|
|||
};
|
||||
export declare type SelectOption = {
|
||||
dontCollect?: boolean;
|
||||
ignoreTrigger?: true;
|
||||
blockTrigger?: true;
|
||||
obscure?: boolean;
|
||||
forUpdate?: true;
|
||||
includedDeleted?: true;
|
||||
dummy?: 1;
|
||||
};
|
||||
export declare type OperateOption = {
|
||||
blockTrigger?: true;
|
||||
dontCollect?: boolean;
|
||||
dontCreateOper?: boolean;
|
||||
allowExists?: boolean;
|
||||
|
|
@ -38,7 +39,6 @@ export declare type Operation<A extends GenericAction | string, DATA extends Obj
|
|||
action: A;
|
||||
data: DATA;
|
||||
sorter?: SORTER;
|
||||
option?: A extends 'select' ? SelectOption : undefined;
|
||||
} & Filter<A, FILTER>;
|
||||
export declare type Selection<DATA extends Object, FILTER extends Object | undefined = undefined, SORT extends Object | undefined = undefined> = Omit<Operation<'select', DATA, FILTER, SORT>, 'id'>;
|
||||
export interface EntityShape {
|
||||
|
|
@ -143,4 +143,5 @@ export declare type SelectRowShape<E extends GeneralEntityShape, P extends Deduc
|
|||
export declare type SelectionResult<E extends GeneralEntityShape, P extends DeduceProjection<GeneralEntityShape>> = {
|
||||
result: Array<SelectRowShape<E, P>>;
|
||||
};
|
||||
export declare type ActionType = 'readOnly' | 'appendOnly' | 'excludeUpdate' | 'crud';
|
||||
export {};
|
||||
|
|
|
|||
|
|
@ -42,6 +42,12 @@ export declare class OakUserUnpermittedException extends OakUserException {
|
|||
export declare class OakUnloggedInException extends OakUserException {
|
||||
constructor(message?: string);
|
||||
}
|
||||
/**
|
||||
* 用户未登录抛的异常
|
||||
*/
|
||||
export declare class OakRowLockedException extends OakUserException {
|
||||
constructor(message?: string);
|
||||
}
|
||||
/**
|
||||
* 要插入行时,发现已经有相同的行数据
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.makeException = exports.OakCongruentRowExists = exports.OakUnloggedInException = exports.OakUserUnpermittedException = exports.OakInputIllegalException = exports.OakRowInconsistencyException = exports.OakUserException = exports.OakExternalException = exports.OakOperExistedException = exports.OakDataException = exports.OakException = void 0;
|
||||
exports.makeException = exports.OakCongruentRowExists = exports.OakRowLockedException = exports.OakUnloggedInException = exports.OakUserUnpermittedException = exports.OakInputIllegalException = exports.OakRowInconsistencyException = exports.OakUserException = exports.OakExternalException = exports.OakOperExistedException = exports.OakDataException = exports.OakException = void 0;
|
||||
var tslib_1 = require("tslib");
|
||||
var OakException = /** @class */ (function (_super) {
|
||||
tslib_1.__extends(OakException, _super);
|
||||
|
|
@ -138,6 +138,18 @@ var OakUnloggedInException = /** @class */ (function (_super) {
|
|||
}(OakUserException));
|
||||
exports.OakUnloggedInException = OakUnloggedInException;
|
||||
;
|
||||
/**
|
||||
* 用户未登录抛的异常
|
||||
*/
|
||||
var OakRowLockedException = /** @class */ (function (_super) {
|
||||
tslib_1.__extends(OakRowLockedException, _super);
|
||||
function OakRowLockedException(message) {
|
||||
return _super.call(this, message || '该行数据正在被更新中,请稍后再试') || this;
|
||||
}
|
||||
return OakRowLockedException;
|
||||
}(OakUserException));
|
||||
exports.OakRowLockedException = OakRowLockedException;
|
||||
;
|
||||
/**
|
||||
* 要插入行时,发现已经有相同的行数据
|
||||
*/
|
||||
|
|
@ -188,6 +200,9 @@ function makeException(data) {
|
|||
case OakCongruentRowExists.name: {
|
||||
return new OakCongruentRowExists(data.data, data.message);
|
||||
}
|
||||
case OakRowLockedException.name: {
|
||||
return new OakRowLockedException(data.message);
|
||||
}
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { ActionType } from '.';
|
||||
import { EntityDict, EntityShape, InstinctiveAttributes } from './Entity';
|
||||
import { DataType, DataTypeParams } from './schema/DataTypes';
|
||||
export declare type Ref = 'ref';
|
||||
|
|
@ -42,6 +43,8 @@ export interface StorageDesc<SH extends EntityShape> {
|
|||
indexes?: Index<SH>[];
|
||||
config?: EntityConfig;
|
||||
toModi?: true;
|
||||
actions: string[];
|
||||
actionType: ActionType;
|
||||
view?: true;
|
||||
}
|
||||
export declare type StorageSchema<ED extends EntityDict> = {
|
||||
|
|
|
|||
|
|
@ -14,4 +14,5 @@ import cloneDeep from 'lodash/cloneDeep';
|
|||
import pick from 'lodash/pick';
|
||||
import isEqual from 'lodash/isEqual';
|
||||
import union from 'lodash/union';
|
||||
export { unset, pull, uniq, get, set, intersection, omit, merge, cloneDeep, pick, isEqual, union, };
|
||||
import difference from 'lodash/difference';
|
||||
export { unset, pull, uniq, get, set, intersection, omit, merge, cloneDeep, pick, isEqual, union, difference, };
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.union = exports.isEqual = exports.pick = exports.cloneDeep = exports.merge = exports.omit = exports.intersection = exports.set = exports.get = exports.uniq = exports.pull = exports.unset = void 0;
|
||||
exports.difference = exports.union = exports.isEqual = exports.pick = exports.cloneDeep = exports.merge = exports.omit = exports.intersection = exports.set = exports.get = exports.uniq = exports.pull = exports.unset = void 0;
|
||||
var tslib_1 = require("tslib");
|
||||
/**
|
||||
* 避免lodash打包体积过大
|
||||
|
|
@ -30,3 +30,5 @@ var isEqual_1 = tslib_1.__importDefault(require("lodash/isEqual"));
|
|||
exports.isEqual = isEqual_1.default;
|
||||
var union_1 = tslib_1.__importDefault(require("lodash/union"));
|
||||
exports.union = union_1.default;
|
||||
var difference_1 = tslib_1.__importDefault(require("lodash/difference"));
|
||||
exports.difference = difference_1.default;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,13 @@
|
|||
import { ActionDef } from '../types/Action';
|
||||
export type GenericAction = 'create' | 'update' | 'remove' | 'select' | 'count' | 'stat' | 'download';
|
||||
export const genericActions = ['create', 'update', 'remove', 'count', 'stat', 'download', 'select'];
|
||||
export type ReadOnlyAction = 'select' | 'count' | 'stat' | 'download';
|
||||
export type AppendOnlyAction = ReadOnlyAction | 'create';
|
||||
export type ExcludeUpdateAction = AppendOnlyAction | 'remove';
|
||||
export type GenericAction = 'update' | ExcludeUpdateAction;
|
||||
|
||||
export const readOnlyActions = ['count', 'stat', 'download', 'select'];
|
||||
export const appendOnlyActions = readOnlyActions.concat('create');
|
||||
export const excludeUpdateActions = appendOnlyActions.concat('remove');
|
||||
export const genericActions = excludeUpdateActions.concat('update');
|
||||
|
||||
export type AbleAction = 'enable' | 'disable';
|
||||
export type AbleState = 'enabled' | 'disabled';
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
import { EntityDict } from '../base-app-domain';
|
||||
import { createModiRelatedCheckers } from '../store/modi';
|
||||
import { StorageSchema, EntityDict as BaseEntityDict, Context } from '../types';
|
||||
|
||||
export function createCheckers<ED extends EntityDict & BaseEntityDict, Cxt extends Context<ED>>(schema: StorageSchema<ED>){
|
||||
return createModiRelatedCheckers<ED, Cxt>(schema);
|
||||
}
|
||||
|
|
@ -27,6 +27,7 @@ const Schema: Record<string, {
|
|||
sourceFile: ts.SourceFile;
|
||||
locale: ts.ObjectLiteralExpression;
|
||||
toModi: boolean;
|
||||
actionType: string;
|
||||
}> = {};
|
||||
const OneToMany: Record<string, Array<[string, string, boolean]>> = {};
|
||||
const ManyToOne: Record<string, Array<[string, string, boolean]>> = {};
|
||||
|
|
@ -285,7 +286,7 @@ const RESERVED_ACTION_NAMES = ['GenericAction', 'ParticularAction'];
|
|||
import { genericActions } from '../actions/action';
|
||||
import { unIndexedTypes } from '../types/DataType';
|
||||
import { initinctiveAttributes } from '../types/Entity';
|
||||
function dealWithActions(moduleName: string, filename: string, node: ts.TypeNode, program: ts.Program) {
|
||||
function dealWithActions(moduleName: string, filename: string, node: ts.TypeNode, program: ts.Program, sourceFile: ts.SourceFile) {
|
||||
const actionTexts = genericActions.map(
|
||||
ele => ele
|
||||
);
|
||||
|
|
@ -343,8 +344,26 @@ function dealWithActions(moduleName: string, filename: string, node: ts.TypeNode
|
|||
}
|
||||
);
|
||||
|
||||
// 为每个action在schema中建立相应的state域(除了genericState)
|
||||
// 放到actionDef的定义处去做。by Xc
|
||||
pushStatementIntoActionAst(moduleName,
|
||||
factory.createVariableStatement(
|
||||
[factory.createModifier(ts.SyntaxKind.ExportKeyword)],
|
||||
factory.createVariableDeclarationList(
|
||||
[factory.createVariableDeclaration(
|
||||
factory.createIdentifier("actions"),
|
||||
undefined,
|
||||
undefined,
|
||||
factory.createArrayLiteralExpression(
|
||||
actionTexts.map(
|
||||
ele => factory.createStringLiteral(ele)
|
||||
),
|
||||
false
|
||||
)
|
||||
)],
|
||||
ts.NodeFlags.Const
|
||||
)
|
||||
),
|
||||
sourceFile
|
||||
);
|
||||
}
|
||||
|
||||
function getEntityImported(declaration: ts.ImportDeclaration, filename: string) {
|
||||
|
|
@ -429,6 +448,7 @@ function analyzeEntity(filename: string, path: string, program: ts.Program) {
|
|||
let hasRelationDef = false;
|
||||
let hasActionOrStateDef = false;
|
||||
let toModi = false;
|
||||
let actionType = 'crud';
|
||||
const enumStringAttrs: string[] = [];
|
||||
const states: string[] = [];
|
||||
const localEnumStringTypes: string[] = [];
|
||||
|
|
@ -635,7 +655,7 @@ function analyzeEntity(filename: string, path: string, program: ts.Program) {
|
|||
),
|
||||
sourceFile!
|
||||
);
|
||||
dealWithActions(moduleName, filename, node.type, program);
|
||||
dealWithActions(moduleName, filename, node.type, program, sourceFile!);
|
||||
}
|
||||
else if (node.name.text === 'Relation') {
|
||||
assert(!localeDef, `【${filename}】locale定义须在Relation之后`);
|
||||
|
|
@ -685,6 +705,7 @@ function analyzeEntity(filename: string, path: string, program: ts.Program) {
|
|||
[relationEntityName]: {
|
||||
schemaAttrs: relationSchemaAttrs,
|
||||
sourceFile,
|
||||
actionType: 'crud',
|
||||
},
|
||||
});
|
||||
addRelationship(relationEntityName, 'User', 'user', true);
|
||||
|
|
@ -916,12 +937,11 @@ function analyzeEntity(filename: string, path: string, program: ts.Program) {
|
|||
|
||||
indexes = declaration.initializer;
|
||||
}
|
||||
else if (ts.isIdentifier(declaration.name) && declaration.name.text === 'locale') {
|
||||
else if (ts.isTypeReferenceNode(declaration.type!) && ts.isIdentifier(declaration.type.typeName) && declaration.type.typeName.text === 'LocaleDef') {
|
||||
// locale定义
|
||||
const { type, initializer } = declaration;
|
||||
|
||||
assert(ts.isObjectLiteralExpression(initializer!));
|
||||
assert(ts.isTypeReferenceNode(type!) && ts.isIdentifier(type.typeName!) && type.typeName.text === 'LocaleDef', 'locale定义的类型必须是LocaleDef');
|
||||
const { properties } = initializer;
|
||||
assert(properties.length > 0, `${filename}至少需要有一种locale定义`);
|
||||
|
||||
|
|
@ -972,6 +992,10 @@ function analyzeEntity(filename: string, path: string, program: ts.Program) {
|
|||
|
||||
localeDef = initializer;
|
||||
}
|
||||
else if (ts.isTypeReferenceNode(declaration.type!) && ts.isIdentifier(declaration.type.typeName) && declaration.type.typeName.text === 'ActionType') {
|
||||
assert(ts.isStringLiteral(declaration.initializer!));
|
||||
actionType = declaration.initializer.text;
|
||||
}
|
||||
else {
|
||||
throw new Error(`不能理解的定义内容${declaration.name.getText()}`);
|
||||
}
|
||||
|
|
@ -983,11 +1007,15 @@ function analyzeEntity(filename: string, path: string, program: ts.Program) {
|
|||
if (!hasActionDef && hasActionOrStateDef) {
|
||||
throw new Error(`${filename}中有Action或State定义,但没有定义完整的Action类型`);
|
||||
}
|
||||
if (hasActionDef && actionType !== 'crud') {
|
||||
throw new Error(`${filename}中有Action定义,但却定义了actionType不是crud`);
|
||||
}
|
||||
assert(schemaAttrs.length > 0);
|
||||
const schema = {
|
||||
schemaAttrs,
|
||||
sourceFile,
|
||||
toModi,
|
||||
actionType,
|
||||
};
|
||||
if (hasFulltextIndex) {
|
||||
assign(schema, {
|
||||
|
|
@ -1510,17 +1538,17 @@ function constructFilter(statements: Array<ts.Statement>, entity: string) {
|
|||
if (ReversePointerRelations[entity]) {
|
||||
// 有反向指针,将反向指针关联的对象的Filter也注入
|
||||
ReversePointerRelations[entity].forEach(
|
||||
ele =>
|
||||
members.push(
|
||||
factory.createPropertySignature(
|
||||
undefined,
|
||||
firstLetterLowerCase(ele),
|
||||
undefined,
|
||||
factory.createTypeReferenceNode(
|
||||
createForeignRef(entity, ele, 'Filter')
|
||||
ele =>
|
||||
members.push(
|
||||
factory.createPropertySignature(
|
||||
undefined,
|
||||
firstLetterLowerCase(ele),
|
||||
undefined,
|
||||
factory.createTypeReferenceNode(
|
||||
createForeignRef(entity, ele, 'Filter')
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
const eumUnionTypeNode: ts.TypeNode[] = ReversePointerRelations[entity] && ReversePointerRelations[entity].map(
|
||||
|
|
@ -4922,7 +4950,7 @@ function outputStorage(outputDir: string, printer: ts.Printer) {
|
|||
|
||||
for (const entity in Schema) {
|
||||
const indexExpressions: ts.Expression[] = [];
|
||||
const { sourceFile, fulltextIndex, indexes, toModi } = Schema[entity];
|
||||
const { sourceFile, fulltextIndex, indexes, toModi, actionType } = Schema[entity];
|
||||
const statements: ts.Statement[] = [
|
||||
factory.createImportDeclaration(
|
||||
undefined,
|
||||
|
|
@ -4955,8 +4983,110 @@ function outputStorage(outputDir: string, printer: ts.Printer) {
|
|||
undefined
|
||||
)
|
||||
];
|
||||
switch (actionType) {
|
||||
case 'readOnly': {
|
||||
statements.push(
|
||||
factory.createImportDeclaration(
|
||||
undefined,
|
||||
undefined,
|
||||
factory.createImportClause(
|
||||
false,
|
||||
undefined,
|
||||
factory.createNamedImports([factory.createImportSpecifier(
|
||||
false,
|
||||
factory.createIdentifier("readOnlyActions"),
|
||||
factory.createIdentifier("actions")
|
||||
)])
|
||||
),
|
||||
factory.createStringLiteral(ACTION_CONSTANT_IN_OAK_DOMAIN()),
|
||||
undefined
|
||||
)
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 'appendOnly': {
|
||||
statements.push(
|
||||
factory.createImportDeclaration(
|
||||
undefined,
|
||||
undefined,
|
||||
factory.createImportClause(
|
||||
false,
|
||||
undefined,
|
||||
factory.createNamedImports([factory.createImportSpecifier(
|
||||
false,
|
||||
factory.createIdentifier("appendOnlyActions"),
|
||||
factory.createIdentifier("actions")
|
||||
)])
|
||||
),
|
||||
factory.createStringLiteral(ACTION_CONSTANT_IN_OAK_DOMAIN()),
|
||||
undefined
|
||||
)
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 'excludeUpdate': {
|
||||
statements.push(
|
||||
factory.createImportDeclaration(
|
||||
undefined,
|
||||
undefined,
|
||||
factory.createImportClause(
|
||||
false,
|
||||
undefined,
|
||||
factory.createNamedImports([factory.createImportSpecifier(
|
||||
false,
|
||||
factory.createIdentifier("excludeUpdateActions"),
|
||||
factory.createIdentifier("actions")
|
||||
)])
|
||||
),
|
||||
factory.createStringLiteral(ACTION_CONSTANT_IN_OAK_DOMAIN()),
|
||||
undefined
|
||||
)
|
||||
);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if (ActionAsts[entity]) {
|
||||
statements.push(
|
||||
factory.createImportDeclaration(
|
||||
undefined,
|
||||
undefined,
|
||||
factory.createImportClause(
|
||||
false,
|
||||
undefined,
|
||||
factory.createNamedImports([factory.createImportSpecifier(
|
||||
false,
|
||||
undefined,
|
||||
factory.createIdentifier("actions")
|
||||
)])
|
||||
),
|
||||
factory.createStringLiteral("./Action"),
|
||||
undefined
|
||||
)
|
||||
);
|
||||
}
|
||||
else {
|
||||
statements.push(
|
||||
factory.createImportDeclaration(
|
||||
undefined,
|
||||
undefined,
|
||||
factory.createImportClause(
|
||||
false,
|
||||
undefined,
|
||||
factory.createNamedImports([factory.createImportSpecifier(
|
||||
false,
|
||||
factory.createIdentifier("genericActions"),
|
||||
factory.createIdentifier("actions")
|
||||
)])
|
||||
),
|
||||
factory.createStringLiteral(ACTION_CONSTANT_IN_OAK_DOMAIN()),
|
||||
undefined
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const propertyAssignments: ts.PropertyAssignment[] = [];
|
||||
const propertyAssignments: (ts.PropertyAssignment | ts.ShorthandPropertyAssignment)[] = [];
|
||||
const attributes = constructAttributes(entity);
|
||||
propertyAssignments.push(
|
||||
factory.createPropertyAssignment(
|
||||
|
|
@ -4982,6 +5112,17 @@ function outputStorage(outputDir: string, printer: ts.Printer) {
|
|||
);
|
||||
}
|
||||
|
||||
propertyAssignments.push(
|
||||
factory.createPropertyAssignment(
|
||||
factory.createIdentifier("actionType"),
|
||||
factory.createStringLiteral(actionType)
|
||||
),
|
||||
factory.createShorthandPropertyAssignment(
|
||||
factory.createIdentifier("actions"),
|
||||
undefined
|
||||
)
|
||||
);
|
||||
|
||||
if (indexExpressions.length > 0) {
|
||||
propertyAssignments.push(
|
||||
factory.createPropertyAssignment(
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { String } from '../types/DataType';
|
||||
import { EntityShape } from '../types/Entity';
|
||||
import { EntityShape, ActionType } from '../types/Entity';
|
||||
import { LocaleDef } from '../types/Locale';
|
||||
import { Schema as Modi } from './Modi';
|
||||
|
||||
|
|
@ -9,6 +9,7 @@ export interface Schema extends EntityShape {
|
|||
entityId: String<64>;
|
||||
};
|
||||
|
||||
const actionType: ActionType = 'appendOnly';
|
||||
|
||||
const locale: LocaleDef<Schema, '', '', {}> = {
|
||||
zh_CN: {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { String, Int, Datetime, Image, Boolean, Text } from '../types/DataType';
|
||||
import { EntityShape } from '../types/Entity';
|
||||
import { EntityShape, ActionType } from '../types/Entity';
|
||||
import { LocaleDef } from '../types/Locale';
|
||||
import { Schema as User } from './User';
|
||||
|
||||
|
|
@ -11,6 +11,8 @@ export interface Schema extends EntityShape {
|
|||
operator?: User;
|
||||
};
|
||||
|
||||
const actionType: ActionType = 'appendOnly';
|
||||
|
||||
const locale: LocaleDef<Schema, '', '', {}> = {
|
||||
zh_CN: {
|
||||
attr: {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { String } from '../types/DataType';
|
||||
import { EntityShape } from '../types/Entity';
|
||||
import { EntityShape, ActionType } from '../types/Entity';
|
||||
import { LocaleDef } from '../types/Locale';
|
||||
import { Schema as Oper } from './Oper';
|
||||
|
||||
|
|
@ -9,6 +9,7 @@ export interface Schema extends EntityShape {
|
|||
entityId: String<64>;
|
||||
};
|
||||
|
||||
const actionType: ActionType = 'appendOnly';
|
||||
|
||||
const locale: LocaleDef<Schema, '', '', {}> = {
|
||||
zh_CN: {
|
||||
|
|
|
|||
|
|
@ -633,7 +633,7 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict, Cxt e
|
|||
|
||||
switch (action) {
|
||||
case 'create': {
|
||||
if (option.modiParentEntity && !['modi', 'modiEntity'].includes(entity as string)) {
|
||||
if (option.modiParentEntity && !['modi', 'modiEntity', 'oper', 'operEntity'].includes(entity as string)) {
|
||||
// 变成对modi的插入
|
||||
const modiCreate: CreateModiOperation = {
|
||||
id: 'dummy',
|
||||
|
|
|
|||
|
|
@ -1,5 +1,10 @@
|
|||
import { OpSchema as Modi } from '../base-app-domain/Modi/Schema';
|
||||
import { Operation } from '../types';
|
||||
import { EntityDict } from '../base-app-domain';
|
||||
import { UniversalContext } from '../store/UniversalContext';
|
||||
import { OpSchema as Modi, Filter } from '../base-app-domain/Modi/Schema';
|
||||
import { Checker, Operation, StorageSchema, UpdateChecker, EntityDict as BaseEntityDict, OakRowLockedException, Context } from '../types';
|
||||
import { appendOnlyActions } from '../actions/action';
|
||||
import { difference } from '../utils/lodash';
|
||||
|
||||
export function createOperationsFromModies(modies: Modi[]): Array<{
|
||||
operation: Operation <string, Object, Object>,
|
||||
entity: string,
|
||||
|
|
@ -17,4 +22,93 @@ export function createOperationsFromModies(modies: Modi[]): Array<{
|
|||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
export async function applyModis<ED extends EntityDict, Cxt extends UniversalContext<ED>>(filter: Filter, context: Cxt) {
|
||||
return context.rowStore.operate('modi', {
|
||||
id: await generateNewId(),
|
||||
action: 'apply',
|
||||
data: {},
|
||||
filter,
|
||||
sorter: [
|
||||
{
|
||||
$attr: {
|
||||
$$createAt$$: 1,
|
||||
},
|
||||
$direction: 'asc',
|
||||
}
|
||||
]
|
||||
}, context, {
|
||||
dontCollect: true,
|
||||
blockTrigger: true,
|
||||
});
|
||||
}
|
||||
|
||||
export async function abandonModis<ED extends EntityDict, Cxt extends UniversalContext<ED>>(filter: Filter, context: Cxt) {
|
||||
return context.rowStore.operate('modi', {
|
||||
id: await generateNewId(),
|
||||
action: 'abadon',
|
||||
data: {},
|
||||
filter,
|
||||
sorter: [
|
||||
{
|
||||
$attr: {
|
||||
$$createAt$$: 1,
|
||||
},
|
||||
$direction: 'asc',
|
||||
}
|
||||
]
|
||||
}, context, {
|
||||
dontCollect: true,
|
||||
blockTrigger: true,
|
||||
});
|
||||
}
|
||||
|
||||
export function createModiRelatedCheckers<ED extends EntityDict & BaseEntityDict, Cxt extends Context<ED>>(schema: StorageSchema<ED>) {
|
||||
const checkers:Checker<ED, keyof ED, Cxt>[] = [];
|
||||
|
||||
for (const entity in schema) {
|
||||
const { actionType, actions } = schema[entity];
|
||||
if (['modi', 'modiEntity', 'oper', 'operEntity'].includes(entity) || ['readOnly', 'appendOnly'].includes(actionType)) {
|
||||
continue;
|
||||
}
|
||||
const restActions = difference(actions, appendOnlyActions);
|
||||
checkers.push({
|
||||
entity,
|
||||
action: restActions as any,
|
||||
type: 'row',
|
||||
checker: async ({ operation }, context) => {
|
||||
const { filter } = operation;
|
||||
const filter2 = {
|
||||
modi: {
|
||||
iState: 'active',
|
||||
},
|
||||
};
|
||||
if (filter) {
|
||||
Object.assign(filter2, {
|
||||
[entity]: filter
|
||||
});
|
||||
}
|
||||
else {
|
||||
Object.assign(filter2, {
|
||||
entity,
|
||||
});
|
||||
}
|
||||
const count = await context.rowStore.count(
|
||||
'modiEntity',
|
||||
{
|
||||
filter: filter2 as any,
|
||||
},
|
||||
context,
|
||||
{}
|
||||
);
|
||||
if (count > 0) {
|
||||
throw new OakRowLockedException();
|
||||
}
|
||||
return 0;
|
||||
},
|
||||
} as UpdateChecker<ED, keyof ED, Cxt>)
|
||||
}
|
||||
|
||||
return checkers;
|
||||
}
|
||||
|
|
@ -28,7 +28,9 @@ const triggers: Trigger<EntityDict, 'modi', UniversalContext<EntityDict>>[] = [
|
|||
action,
|
||||
data,
|
||||
filter: filter as any,
|
||||
}, context, option);
|
||||
}, context, Object.assign({}, option, {
|
||||
blockTrigger: true,
|
||||
}));
|
||||
}
|
||||
|
||||
return modies.length;
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ export type Filter<A extends string, F extends Object | undefined = undefined> =
|
|||
|
||||
export type SelectOption = {
|
||||
dontCollect?: boolean;
|
||||
ignoreTrigger?: true;
|
||||
blockTrigger?: true;
|
||||
obscure?: boolean; // 如果为置为true,则在filter过程中因数据不完整而不能判断为真的时候都假设为真(前端缓存专用)
|
||||
forUpdate?: true;
|
||||
includedDeleted?: true; // 是否包含删除行的信息
|
||||
|
|
@ -25,6 +25,7 @@ export type SelectOption = {
|
|||
};
|
||||
|
||||
export type OperateOption = {
|
||||
blockTrigger?: true;
|
||||
dontCollect?: boolean;
|
||||
dontCreateOper?: boolean;
|
||||
allowExists?: boolean; // 插入时允许已经存在唯一键值的行了,即insert / update逻辑
|
||||
|
|
@ -47,7 +48,6 @@ export type Operation<A extends GenericAction | string,
|
|||
action: A;
|
||||
data: DATA;
|
||||
sorter?: SORTER;
|
||||
option?: A extends 'select' ? SelectOption : undefined;
|
||||
} & Filter<A, FILTER>;
|
||||
|
||||
export type Selection<DATA extends Object,
|
||||
|
|
@ -204,3 +204,5 @@ export type SelectRowShape<E extends GeneralEntityShape, P extends DeduceProject
|
|||
export type SelectionResult<E extends GeneralEntityShape, P extends DeduceProjection<GeneralEntityShape>> = {
|
||||
result: Array<SelectRowShape<E, P>>;
|
||||
}
|
||||
|
||||
export type ActionType = 'readOnly' | 'appendOnly' | 'excludeUpdate' | 'crud'; // 只读型、只插入型、没有更新型、所有型
|
||||
|
|
|
|||
|
|
@ -108,6 +108,15 @@ export class OakUnloggedInException extends OakUserException {
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 用户未登录抛的异常
|
||||
*/
|
||||
export class OakRowLockedException extends OakUserException {
|
||||
constructor(message?: string) {
|
||||
super(message || '该行数据正在被更新中,请稍后再试');
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 要插入行时,发现已经有相同的行数据
|
||||
*/
|
||||
|
|
@ -162,6 +171,9 @@ export function makeException(data: {
|
|||
case OakCongruentRowExists.name: {
|
||||
return new OakCongruentRowExists(data.data, data.message);
|
||||
}
|
||||
case OakRowLockedException.name: {
|
||||
return new OakRowLockedException(data.message);
|
||||
}
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { ActionType } from '.';
|
||||
import { EntityDict, EntityShape, InstinctiveAttributes } from './Entity';
|
||||
import { DataType, DataTypeParams } from './schema/DataTypes';
|
||||
|
||||
|
|
@ -52,7 +53,9 @@ export interface StorageDesc<SH extends EntityShape> {
|
|||
uniqueConstraints?: UniqConstraint<SH>[];
|
||||
indexes?: Index<SH>[];
|
||||
config?: EntityConfig;
|
||||
toModi?: true, // 标识一下是否关联在modi上
|
||||
toModi?: true; // 标识一下是否关联在modi上
|
||||
actions: string[];
|
||||
actionType: ActionType;
|
||||
// view 相关
|
||||
view?: true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import cloneDeep from 'lodash/cloneDeep';
|
|||
import pick from 'lodash/pick';
|
||||
import isEqual from 'lodash/isEqual';
|
||||
import union from 'lodash/union';
|
||||
import difference from 'lodash/difference';
|
||||
|
||||
export {
|
||||
unset,
|
||||
|
|
@ -28,4 +29,5 @@ export {
|
|||
pick,
|
||||
isEqual,
|
||||
union,
|
||||
difference,
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue