oak-domain/lib/types/Exception.js

622 lines
21 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.makeException = exports.OakApplicationHasToUpgrade = exports.OakSocketConnectException = exports.OakExternalException = exports.OakPreConditionUnsetException = exports.OakDeadlock = exports.OakCongruentRowExists = exports.OakRowLockedException = exports.OakUnloggedInException = exports.OakDataInvisibleException = exports.OakOperationUnpermittedException = exports.OakAttrCantUpdateException = exports.OakAttrNotNullException = exports.OakInputIllegalException = exports.OakRowInconsistencyException = exports.OakSignatureVerificationException = exports.OakInsecureRequestException = exports.OakClockDriftException = exports.OakServerProxyException = exports.OakNetworkException = exports.OakImportDataParseException = exports.OakUniqueViolationException = exports.OakUserException = exports.OakRowUnexistedException = exports.OakOperExistedException = exports.OakNoRelationDefException = exports.OakDataException = exports.OakPartialSuccess = exports.OakMakeSureByMySelfException = exports.OakRequestTimeoutException = exports.OakException = exports.isOakException = void 0;
const relation_1 = require("../store/relation");
const lodash_1 = require("../utils/lodash");
const OAK_EXCEPTION_SYMBOL = Symbol.for('oak-domain:exception');
/**
* 判断一个对象是否为 OakException 实例,作用和 `instanceof` 类似,但更安全可靠。
* 如OakUserException继承自OakException使用时可传入OakUserException以进一步确认类型。
* @param obj 需要判断的对象
* @param exceptionName 可选参数,指定异常类名以进一步确认
*
* ```ts
* if (isOakException(e, OakUserException)) {
* // 这里的 e 已被类型缩小为 OakUserException
* }
* ```
*
* @returns 如果对象是 OakException 实例则返回 true否则返回 false
*/
function isOakException(obj, errType) {
if (!obj) {
return false;
}
const isOakException = !!obj[OAK_EXCEPTION_SYMBOL];
if (isOakException) {
if (!errType) {
return true;
}
}
else {
return false;
}
try {
let proto = Object.getPrototypeOf(obj);
const expectedName = errType.name;
let depth = 0;
const maxDepth = 10; // 防止无限循环
while (proto && depth < maxDepth) {
const constructorName = proto.constructor?.name;
if (constructorName === expectedName) {
return true;
}
proto = Object.getPrototypeOf(proto);
depth++;
}
return false;
}
catch (e) {
console.warn(e);
// 如果检查过程出错,安全返回 false
return false;
}
}
exports.isOakException = isOakException;
class OakException extends Error {
opRecords;
_module;
params;
[OAK_EXCEPTION_SYMBOL] = true;
constructor(message, _module, params) {
super(message);
this._module = _module;
this.params = params;
this.name = new.target.name;
if (typeof Error.captureStackTrace === 'function') {
Error.captureStackTrace(this, new.target);
}
if (typeof Object.setPrototypeOf === 'function') {
Object.setPrototypeOf(this, new.target.prototype);
}
else {
this.__proto__ = new.target.prototype;
}
this.opRecords = [];
}
addData(entity, rows, schema) {
const rowDict = {};
const addToRowDict = (entity, row) => {
if (!rowDict[entity]) {
rowDict[entity] = {
[row.id]: row,
};
}
else {
if (rowDict[entity][row.id]) {
Object.assign(rowDict[entity][row.id], row);
}
else {
rowDict[entity][row.id] = row;
}
}
};
const addInner = (entity, row) => {
const ownAttrs = [];
for (const attr in row) {
const rel = (0, relation_1.judgeRelation)(schema, entity, attr);
if (rel === 1) {
ownAttrs.push(attr);
}
else if (rel === 2) {
addInner(attr, row[attr]);
}
else if (typeof rel === 'string') {
addInner(rel, row[attr]);
}
else if (rel instanceof Array) {
(row[attr]).forEach((ele) => addInner(rel[0], ele));
}
}
addToRowDict(entity, (0, lodash_1.pick)(row, ownAttrs));
};
for (const row of rows) {
addInner(entity, row);
}
for (const entity in rowDict) {
const record = {
a: 's',
d: {
[entity]: rowDict[entity],
}
};
this.opRecords.push(record);
}
}
setOpRecords(opRecords) {
this.opRecords = opRecords;
}
getSerialData() {
return {
name: this.constructor.name,
message: this.message,
_module: this._module,
params: this.params,
opRecords: this.opRecords,
tag1: this.tag1,
tag2: this.tag2,
tag3: this.tag3,
};
}
toString() {
return JSON.stringify(this.getSerialData());
}
// 留三个tag1供其它类使用
tag1;
tag2;
tag3;
}
exports.OakException = OakException;
// 请求超时
class OakRequestTimeoutException extends OakException {
constructor(message, ns, params) {
super(message || 'error::requestTimeout', ns || 'oak-domain', params);
}
}
exports.OakRequestTimeoutException = OakRequestTimeoutException;
// 这个异常表示模块自己处理跨事务一致性框架pass在分布式数据传递时会用到backend-base老版本有使用先保留
class OakMakeSureByMySelfException extends OakException {
}
exports.OakMakeSureByMySelfException = OakMakeSureByMySelfException;
// 这个异常表示事务虽然没有完全成功,但是仍然应该提交并抛出异常(在分布式数据传递时会用到)
class OakPartialSuccess extends OakException {
}
exports.OakPartialSuccess = OakPartialSuccess;
class OakDataException extends OakException {
}
exports.OakDataException = OakDataException;
class OakNoRelationDefException extends OakDataException {
entity;
actions;
constructor(entity, actions, msg, _module, params) {
super(msg || 'error::noRelationDef', _module || 'oak-domain', params || {
entity,
actions: actions.join(',')
});
this.entity = entity;
this.actions = actions;
}
toString() {
const data = super.getSerialData();
return JSON.stringify({
...data,
entity: this.entity,
action: this.actions,
});
}
}
exports.OakNoRelationDefException = OakNoRelationDefException;
class OakOperExistedException extends OakDataException {
}
exports.OakOperExistedException = OakOperExistedException;
class OakRowUnexistedException extends OakDataException {
rows;
// 指定主键查询时却发现行不存在,一般发生在缓存中
constructor(rows, msg, _module, params) {
super(msg || 'error::rowUnexisted', _module || 'oak-domain', params || {
entity: rows[0].entity,
});
this.rows = rows;
}
toString() {
const data = super.getSerialData();
return JSON.stringify({
...data,
rows: this.rows
});
}
getRows() {
return this.rows;
}
}
exports.OakRowUnexistedException = OakRowUnexistedException;
/**
* 可接受的、由用户操作造成的异常
*/
class OakUserException extends OakException {
}
exports.OakUserException = OakUserException;
;
class OakUniqueViolationException extends OakUserException {
rows;
constructor(rows, message, _module, params) {
super(message || 'error::uniqViolation', _module || 'oak-domain', params);
this.rows = rows;
}
}
exports.OakUniqueViolationException = OakUniqueViolationException;
class OakImportDataParseException extends OakUserException {
line;
header;
// message必传描述具体错误的数据内容
constructor(message, line, header, _module, params) {
super(message || 'error::importedDataParseError', _module || 'oak-domain', params);
this.line = line;
this.header = header;
}
}
exports.OakImportDataParseException = OakImportDataParseException;
/**
* 网络中断异常
*/
class OakNetworkException extends OakException {
}
exports.OakNetworkException = OakNetworkException;
// 请求未到达应用服务程序
class OakServerProxyException extends OakException {
}
exports.OakServerProxyException = OakServerProxyException;
// 时钟漂移过久(重放攻击)
class OakClockDriftException extends OakException {
}
exports.OakClockDriftException = OakClockDriftException;
// 非安全的请求(未加密)
class OakInsecureRequestException extends OakException {
}
exports.OakInsecureRequestException = OakInsecureRequestException;
// 验签失败
class OakSignatureVerificationException extends OakException {
constructor(message, _module, params) {
super(message || 'error::signatureFailed', _module || 'oak-domain', params);
}
}
exports.OakSignatureVerificationException = OakSignatureVerificationException;
// 在系统更新数据时,以下三个异常应按规范依次抛出。
/**
* 数据不一致异常,系统认为现有的数据不允许相应的动作时抛此异常
*
*/
class OakRowInconsistencyException extends OakUserException {
toString() {
const data = super.getSerialData();
return JSON.stringify(data);
}
}
exports.OakRowInconsistencyException = OakRowInconsistencyException;
;
/**
* 当输入的数据非法时抛此异常attributes表示非法的属性
*/
class OakInputIllegalException extends OakUserException {
attributes;
entity;
constructor(entity, attributes, message, _module, params) {
super(message, _module, params || {
entity,
attributes: attributes.join(','),
});
this.entity = entity;
this.attributes = attributes;
}
getEntity() {
return this.entity;
}
getAttributes() {
return this.attributes;
}
addAttributesPrefix(prefix) {
this.attributes = this.attributes.map(ele => `${prefix}.${ele}`);
}
toString() {
const data = super.getSerialData();
return JSON.stringify({
...data,
entity: this.entity,
attributes: this.attributes,
});
}
}
exports.OakInputIllegalException = OakInputIllegalException;
;
/**
* 属性为空时抛的异常
*/
class OakAttrNotNullException extends OakInputIllegalException {
constructor(entity, attributes, message, _module, params) {
super(entity, attributes, message || 'error::attributesNull', _module || 'oak-domain', params);
}
}
exports.OakAttrNotNullException = OakAttrNotNullException;
/**
* 属性不允许更新抛的异常前端可以用这个异常来处理update时对应属性的露出
*/
class OakAttrCantUpdateException extends OakInputIllegalException {
constructor(entity, attributes, message, _module, params) {
super(entity, attributes, message || 'error::attributesCantUpdate', _module || 'oak-domain', params);
}
}
exports.OakAttrCantUpdateException = OakAttrCantUpdateException;
/**
* 用户权限不够时抛的异常
*/
class OakOperationUnpermittedException extends OakUserException {
entity;
operation;
userId;
constructor(entity, operation, userId, message, _module, params) {
super(message || 'error::operationUnpermitted', _module || 'oak-domain', params);
this.entity = entity;
this.operation = operation;
this.userId = userId;
}
toString() {
const data = super.getSerialData();
return JSON.stringify({
...data,
entity: this.entity,
operation: this.operation,
userId: this.userId,
});
}
}
exports.OakOperationUnpermittedException = OakOperationUnpermittedException;
;
/**
* 用户查询权限不够抛出异常
*/
class OakDataInvisibleException extends OakUserException {
entity;
operation;
userId;
constructor(entity, operation, userId, message, _module, params) {
super(message || 'error::dataInvisible', _module || 'oak-domain', params);
this.entity = entity;
this.operation = operation;
this.userId = userId;
}
toString() {
const data = super.getSerialData();
return JSON.stringify({
...data,
entity: this.entity,
operation: this.operation,
userId: this.userId,
});
}
}
exports.OakDataInvisibleException = OakDataInvisibleException;
;
/**
* 用户未登录抛的异常
*/
class OakUnloggedInException extends OakUserException {
constructor(message, _module, params) {
super(message || 'error::unLoggedIn', _module || 'oak-domain', params);
}
}
exports.OakUnloggedInException = OakUnloggedInException;
;
/**
* 行数据被锁抛的异常
*/
class OakRowLockedException extends OakUserException {
constructor(message, _module, params) {
super(message || 'error::rowLocked', _module || 'oak-domain', params);
}
}
exports.OakRowLockedException = OakRowLockedException;
;
/**
* 要插入行时,发现已经有相同的行数据
*/
class OakCongruentRowExists extends OakUserException {
data;
entity;
constructor(entity, data, message, _module, params) {
super(message || 'error::congrentRowExists', _module || 'oak-domain', params);
this.data = data;
this.entity = entity;
}
getData() {
return this.data;
}
getEntity() {
return this.entity;
}
toString() {
const data = super.getSerialData();
return JSON.stringify({
...data,
data: this.data,
entity: this.entity,
});
}
}
exports.OakCongruentRowExists = OakCongruentRowExists;
/**
* 死锁抛的异常
*/
class OakDeadlock extends OakUserException {
constructor(message, _module, params) {
super(message || 'error::deadlock', _module || 'oak-domain', params);
}
}
exports.OakDeadlock = OakDeadlock;
;
/**
* 前置条件不满足抛的异常
*/
class OakPreConditionUnsetException extends OakUserException {
entity;
code;
constructor(message, entity, code, _module, params) {
super(message || 'error::preconditionUnset', _module || 'oak-domain', params);
this.entity = entity,
this.code = code;
}
toString() {
const data = super.getSerialData();
return JSON.stringify({
...data,
code: this.code,
entity: this.entity,
});
}
}
exports.OakPreConditionUnsetException = OakPreConditionUnsetException;
/**
* 调用外部接口抛出的异常
*/
class OakExternalException extends OakUserException {
code;
source;
data;
constructor(source, code, message, data, _module, params) {
super(message || 'error::externalException', _module || 'oak-domain', params);
this.code = code;
this.source = source;
this.data = data;
}
toString() {
const data = super.getSerialData();
return JSON.stringify({
...data,
code: this.code,
source: this.source,
data: this.data,
});
}
}
exports.OakExternalException = OakExternalException;
/**
* socket连接异常
*/
class OakSocketConnectException extends OakUserException {
constructor(message, _module, params) {
super(message || 'error::socketConnectException', _module || 'oak-domain', params);
}
}
exports.OakSocketConnectException = OakSocketConnectException;
;
class OakApplicationHasToUpgrade extends OakUserException {
constructor(message, _module, params) {
super(message || 'error::applicationHasToUpgrade', _module || 'oak-domain', params);
}
}
exports.OakApplicationHasToUpgrade = OakApplicationHasToUpgrade;
function makeException(data) {
const { name, message, _module, params } = data;
let e = undefined;
switch (name) {
case 'OakException': {
e = new OakException(message, _module, params);
break;
}
case 'OakUserException': {
e = new OakUserException(message, _module, params);
break;
}
case 'OakRowInconsistencyException': {
e = new OakRowInconsistencyException(message, _module, params);
break;
}
case 'OakInputIllegalException': {
e = new OakInputIllegalException(data.entity, data.attributes, message, _module, params);
break;
}
case 'OakAttrCantUpdateException': {
e = new OakAttrCantUpdateException(data.entity, data.attributes, message, _module, params);
break;
}
case 'OakOperationUnpermittedException': {
e = new OakOperationUnpermittedException(data.entity, data.operation, data.userId, message, _module, params);
break;
}
case 'OakDataInvisibleException': {
e = new OakDataInvisibleException(data.entity, data.operation, data.userId, message, _module, params);
break;
}
case 'OakUnloggedInException': {
e = new OakUnloggedInException(message, _module, params);
break;
}
case 'OakCongruentRowExists': {
e = new OakCongruentRowExists(data.entity, data.data, message, _module, params);
break;
}
case 'OakRowLockedException': {
e = new OakRowLockedException(message, _module, params);
break;
}
case 'OakRowUnexistedException': {
e = new OakRowUnexistedException(data.rows, message, _module, params);
break;
}
case 'OakDeadlock': {
e = new OakDeadlock(message, _module, params);
break;
}
case 'OakDataException': {
e = new OakDataException(message, _module, params);
break;
}
case 'OakNoRelationDefException': {
e = new OakNoRelationDefException(data.entity, data.action, message, _module, params);
break;
}
case 'OakUniqueViolationException': {
e = new OakUniqueViolationException(data.rows, message, _module, params);
break;
}
case 'OakImportDataParseException': {
e = new OakImportDataParseException(message, data.line, data.header, _module, params);
break;
}
case 'OakPreConditionUnsetException': {
e = new OakPreConditionUnsetException(message, data.entity, data.code, _module, params);
break;
}
case 'OakAttrNotNullException': {
e = new OakAttrNotNullException(data.entity, data.attributes, message, _module, params);
break;
}
case 'OakExternalException': {
e = new OakExternalException(data.source, data.code, message, data.data, _module, params);
break;
}
case 'OakNetworkException': {
e = new OakNetworkException(message, _module, params);
break;
}
case 'OakClockDriftException': {
e = new OakClockDriftException(message, _module, params);
break;
}
case 'OakInsecureRequestException': {
e = new OakInsecureRequestException(message, _module, params);
break;
}
case 'OakServerProxyException': {
e = new OakServerProxyException(message, _module, params);
break;
}
case 'OakSocketConnectException': {
e = new OakSocketConnectException(message, _module, params);
break;
}
case 'OakPartialSuccess': {
e = new OakPartialSuccess(message, _module, params);
break;
}
case 'OakRequestTimeoutException': {
e = new OakRequestTimeoutException(message, _module, params);
break;
}
case 'OakSignatureVerificationException': {
e = new OakSignatureVerificationException(message, _module, params);
break;
}
case 'OakApplicationHasToUpgrade': {
e = new OakApplicationHasToUpgrade(message, _module, params);
break;
}
default:
return;
}
if (e) {
e.setOpRecords(data.opRecords);
return e;
}
}
exports.makeException = makeException;