408 lines
13 KiB
JavaScript
408 lines
13 KiB
JavaScript
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
exports.triggers = exports.actionAuthTriggers = void 0;
|
||
const tslib_1 = require("tslib");
|
||
const types_1 = require("../types");
|
||
const uuid_1 = require("../utils/uuid");
|
||
const assert_1 = tslib_1.__importDefault(require("assert"));
|
||
const filter_1 = require("./filter");
|
||
exports.actionAuthTriggers = [
|
||
{
|
||
name: '当actionAuth的deActions被置空后,删除此条数据',
|
||
entity: 'actionAuth',
|
||
action: 'update',
|
||
fn: async ({ operation }, context, option) => {
|
||
const { data, filter } = operation;
|
||
if (data.deActions && data.deActions.length === 0) {
|
||
await context.operate('actionAuth', {
|
||
id: await (0, uuid_1.generateNewIdAsync)(),
|
||
action: 'remove',
|
||
data: {},
|
||
filter,
|
||
}, option);
|
||
return 1;
|
||
}
|
||
return 0;
|
||
},
|
||
when: 'after',
|
||
}
|
||
];
|
||
/**
|
||
* 回滚某条日志的修改
|
||
* @param log
|
||
* @param context
|
||
*/
|
||
async function undoLog(log, context) {
|
||
const { iState, oper$log } = log;
|
||
for (const oper of oper$log) {
|
||
const { action, targetEntity, filter, undoData, iState } = oper;
|
||
(0, assert_1.default)(iState === 'normal', '非正常状态的oper怎能回滚');
|
||
switch (action) {
|
||
case 'create': {
|
||
await context.operate(targetEntity, {
|
||
id: 'dummy',
|
||
action: 'remove',
|
||
data: {},
|
||
filter: filter,
|
||
}, {
|
||
blockTrigger: true,
|
||
dontCreateOper: true,
|
||
});
|
||
break;
|
||
}
|
||
case 'remove': {
|
||
const ids = (0, filter_1.getRelevantIds)(filter);
|
||
(0, assert_1.default)(ids.length > 0);
|
||
for (const id of ids) {
|
||
await context.operate(targetEntity, {
|
||
id: 'dummy',
|
||
action: 'create',
|
||
data: undoData[id],
|
||
}, {
|
||
blockTrigger: true,
|
||
dontCreateOper: true,
|
||
});
|
||
}
|
||
break;
|
||
}
|
||
default: {
|
||
// 全按update处理
|
||
const ids = (0, filter_1.getRelevantIds)(filter);
|
||
(0, assert_1.default)(ids.length > 0);
|
||
for (const id of ids) {
|
||
await context.operate(targetEntity, {
|
||
id: 'dummy',
|
||
action: 'update',
|
||
data: undoData[id],
|
||
filter: {
|
||
id,
|
||
}
|
||
}, {
|
||
blockTrigger: true,
|
||
dontCreateOper: true,
|
||
});
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
await context.operate('log', {
|
||
id: 'dummy',
|
||
action: 'undo',
|
||
data: {
|
||
iState: 'rollbacked',
|
||
oper$log: [{
|
||
id: 'dummy',
|
||
action: 'undo',
|
||
data: {
|
||
iState: 'rollbacked',
|
||
},
|
||
}],
|
||
},
|
||
filter: {
|
||
id: log.id,
|
||
},
|
||
}, {
|
||
blockTrigger: true,
|
||
dontCreateOper: true,
|
||
});
|
||
}
|
||
/**
|
||
* 重做某条日志的修改
|
||
* @param log
|
||
* @param context
|
||
*/
|
||
async function redoLog(log, context) {
|
||
const { oper$log } = log;
|
||
for (const oper of oper$log) {
|
||
const { action, targetEntity, filter, data, iState } = oper;
|
||
(0, assert_1.default)(iState === 'rollbacked', '非正常状态的oper怎能回滚');
|
||
switch (action) {
|
||
case 'create': {
|
||
await context.operate(targetEntity, {
|
||
id: 'dummy',
|
||
action: 'create',
|
||
data: data,
|
||
}, {
|
||
blockTrigger: true,
|
||
dontCreateOper: true,
|
||
});
|
||
break;
|
||
}
|
||
case 'remove': {
|
||
await context.operate(targetEntity, {
|
||
id: 'dummy',
|
||
action: 'remove',
|
||
data: {},
|
||
filter: filter,
|
||
}, {
|
||
blockTrigger: true,
|
||
dontCreateOper: true,
|
||
});
|
||
break;
|
||
}
|
||
default: {
|
||
await context.operate(targetEntity, {
|
||
id: 'dummy',
|
||
action,
|
||
data,
|
||
filter: filter,
|
||
}, {
|
||
blockTrigger: true,
|
||
dontCreateOper: true,
|
||
});
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
await context.operate('log', {
|
||
id: 'dummy',
|
||
action: 'redo',
|
||
data: {
|
||
iState: 'normal',
|
||
oper$log: [{
|
||
id: 'dummy',
|
||
action: 'redo',
|
||
data: {
|
||
iState: 'normal',
|
||
},
|
||
}],
|
||
},
|
||
filter: {
|
||
id: log.id,
|
||
},
|
||
}, {
|
||
blockTrigger: true,
|
||
dontCreateOper: true,
|
||
});
|
||
}
|
||
exports.triggers = [
|
||
{
|
||
name: '当log被undo时,同一entity上所有在其之后的log全部回滚',
|
||
entity: 'log',
|
||
action: 'undo',
|
||
when: 'after',
|
||
fn: async ({ operation }, context) => {
|
||
const { filter } = operation;
|
||
(0, assert_1.default)(filter);
|
||
const ids = (0, filter_1.getRelevantIds)(filter);
|
||
(0, assert_1.default)(ids.length === 1);
|
||
const [log] = await context.select('log', {
|
||
data: {
|
||
id: 1,
|
||
oper$log: {
|
||
$entity: 'oper',
|
||
data: {
|
||
id: 1,
|
||
undoData: 1,
|
||
action: 1,
|
||
targetEntity: 1,
|
||
filter: 1,
|
||
[types_1.SeqAttribute]: 1,
|
||
},
|
||
},
|
||
entity: 1,
|
||
entityId: 1,
|
||
[types_1.SeqAttribute]: 1,
|
||
},
|
||
filter: {
|
||
id: ids[0],
|
||
},
|
||
}, { dontCollect: true });
|
||
const logs = await context.select('log', {
|
||
data: {
|
||
id: 1,
|
||
oper$log: {
|
||
$entity: 'oper',
|
||
data: {
|
||
id: 1,
|
||
undoData: 1,
|
||
action: 1,
|
||
targetEntity: 1,
|
||
filter: 1,
|
||
iState: 1,
|
||
},
|
||
},
|
||
iState: 1,
|
||
entity: 1,
|
||
entityId: 1,
|
||
[types_1.SeqAttribute]: 1,
|
||
},
|
||
filter: {
|
||
iState: 'normal',
|
||
entity: log.entity,
|
||
entityId: log.entityId,
|
||
[types_1.SeqAttribute]: {
|
||
$gte: log[types_1.SeqAttribute],
|
||
},
|
||
},
|
||
sorter: [
|
||
{
|
||
$attr: {
|
||
[types_1.SeqAttribute]: 1,
|
||
},
|
||
$direction: 'desc',
|
||
}
|
||
]
|
||
}, { dontCollect: true });
|
||
(0, assert_1.default)(logs.length > 0);
|
||
for (const log2 of logs) {
|
||
await undoLog(log2, context);
|
||
}
|
||
return logs.length;
|
||
}
|
||
},
|
||
{
|
||
name: '当log被redo时,同一entity上所有在其之前的log全部重做',
|
||
entity: 'log',
|
||
action: 'redo',
|
||
when: 'after',
|
||
fn: async ({ operation }, context) => {
|
||
const { filter } = operation;
|
||
(0, assert_1.default)(filter);
|
||
const ids = (0, filter_1.getRelevantIds)(filter);
|
||
(0, assert_1.default)(ids.length === 1);
|
||
const [log] = await context.select('log', {
|
||
data: {
|
||
id: 1,
|
||
oper$log: {
|
||
$entity: 'oper',
|
||
data: {
|
||
id: 1,
|
||
data: 1,
|
||
action: 1,
|
||
targetEntity: 1,
|
||
filter: 1,
|
||
[types_1.SeqAttribute]: 1,
|
||
},
|
||
},
|
||
iState: 1,
|
||
entity: 1,
|
||
entityId: 1,
|
||
[types_1.SeqAttribute]: 1,
|
||
},
|
||
filter: {
|
||
id: ids[0],
|
||
},
|
||
}, { dontCollect: true });
|
||
const logs = await context.select('log', {
|
||
data: {
|
||
id: 1,
|
||
oper$log: {
|
||
$entity: 'oper',
|
||
data: {
|
||
id: 1,
|
||
data: 1,
|
||
action: 1,
|
||
targetEntity: 1,
|
||
filter: 1,
|
||
iState: 1,
|
||
},
|
||
},
|
||
iState: 1,
|
||
entity: 1,
|
||
entityId: 1,
|
||
[types_1.SeqAttribute]: 1,
|
||
},
|
||
filter: {
|
||
iState: 'rollbacked',
|
||
entity: log.entity,
|
||
entityId: log.entityId,
|
||
[types_1.SeqAttribute]: {
|
||
$lte: log[types_1.SeqAttribute],
|
||
},
|
||
},
|
||
sorter: [
|
||
{
|
||
$attr: {
|
||
[types_1.SeqAttribute]: 1,
|
||
},
|
||
$direction: 'asc',
|
||
}
|
||
]
|
||
}, { dontCollect: true, forUpdate: true });
|
||
(0, assert_1.default)(logs.length > 0);
|
||
for (const log2 of logs) {
|
||
await redoLog(log2, context);
|
||
}
|
||
return logs.length;
|
||
}
|
||
},
|
||
{
|
||
name: '当插入新的日志时,过去的rollbacked状态的日志可以删除',
|
||
entity: 'log',
|
||
action: 'create',
|
||
when: 'after',
|
||
fn: async ({ operation }, context, option) => {
|
||
const { data } = operation;
|
||
(0, assert_1.default)(!(data instanceof Array));
|
||
const { entity, entityId } = data;
|
||
const result = await context.operate('oper', {
|
||
id: 'dummy',
|
||
action: 'remove',
|
||
data: {},
|
||
filter: {
|
||
iState: 'rollbacked',
|
||
log: {
|
||
entity: entity,
|
||
entityId: entityId,
|
||
},
|
||
},
|
||
}, {});
|
||
const result2 = await context.operate('log', {
|
||
id: 'dummy',
|
||
action: 'remove',
|
||
data: {},
|
||
filter: {
|
||
entity: entity,
|
||
entityId: entityId,
|
||
iState: 'rollbacked',
|
||
},
|
||
}, {});
|
||
return (result.oper?.remove || 0) + (result2.log?.remove || 0);
|
||
}
|
||
},
|
||
// 在删除log时,删除与此log关联的oper
|
||
{
|
||
name: '当删除log时,删除与此log关联的oper',
|
||
entity: 'log',
|
||
action: 'remove',
|
||
when: 'before',
|
||
fn: async ({ operation }, context) => {
|
||
const { filter } = operation;
|
||
(0, assert_1.default)(filter);
|
||
// 查询这次删除操作涉及到的所有log
|
||
const result = await context.operate('oper', {
|
||
id: "dummy",
|
||
action: 'remove',
|
||
data: {},
|
||
filter: {
|
||
log: filter,
|
||
}
|
||
}, {});
|
||
return result.oper?.remove || 0;
|
||
}
|
||
},
|
||
// 当删除userRelation时,一并删除掉关联的userEntityClaim,这个设计似乎不是太好
|
||
{
|
||
name: '当删除userRelation时,一并删除掉关联的userEntityClaim',
|
||
action: 'remove',
|
||
entity: 'userRelation',
|
||
when: 'before',
|
||
fn: async ({ operation }, context, option) => {
|
||
const { filter } = operation;
|
||
const close = context.openRootMode();
|
||
const result = await context.operate('userEntityClaim', {
|
||
id: await (0, uuid_1.generateNewIdAsync)(),
|
||
action: 'remove',
|
||
data: {},
|
||
filter: {
|
||
userRelation: filter,
|
||
},
|
||
}, option);
|
||
close();
|
||
return result.userEntityClaim?.remove || 0;
|
||
}
|
||
},
|
||
];
|