From bad76d5b1738120adcaf34ba71b58fa84a3371bf Mon Sep 17 00:00:00 2001 From: Xc Date: Fri, 31 Mar 2023 21:28:33 +0800 Subject: [PATCH 01/10] 2.6.8-dev --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2ca4be7..ca4cd34 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "oak-domain", - "version": "2.6.7", + "version": "2.6.8", "author": { "name": "XuChang" }, From 3b44bbd943739b12da8c8d8a8424737601525aa3 Mon Sep 17 00:00:00 2001 From: Xc Date: Sun, 2 Apr 2023 15:06:33 +0800 Subject: [PATCH 02/10] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=BA=86=E5=AF=B9notNu?= =?UTF-8?q?ll=E5=B1=9E=E6=80=A7=E7=9A=84=E7=BC=96=E8=AF=91=E5=92=8C?= =?UTF-8?q?=E6=A3=80=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/base-app-domain/Modi/Storage.js | 5 ++ lib/base-app-domain/ModiEntity/Storage.js | 3 + lib/base-app-domain/Oper/Storage.js | 3 + lib/base-app-domain/OperEntity/Storage.js | 3 + .../UserEntityGrant/Storage.js | 3 + lib/checkers/index.js | 1 + lib/compiler/schemalBuilder.js | 5 +- lib/store/checker.d.ts | 1 + lib/store/checker.js | 68 ++++++++++++++++- lib/types/Exception.d.ts | 7 +- lib/types/Exception.js | 11 ++- lib/utils/validator.js | 2 +- src/checkers/index.ts | 3 +- src/compiler/schemalBuilder.ts | 10 ++- src/store/checker.ts | 74 ++++++++++++++++++- src/types/Exception.ts | 11 ++- src/utils/validator.ts | 4 +- 17 files changed, 199 insertions(+), 15 deletions(-) diff --git a/lib/base-app-domain/Modi/Storage.js b/lib/base-app-domain/Modi/Storage.js index 2058baf..72680e2 100644 --- a/lib/base-app-domain/Modi/Storage.js +++ b/lib/base-app-domain/Modi/Storage.js @@ -5,30 +5,35 @@ var Action_1 = require("./Action"); exports.desc = { attributes: { targetEntity: { + notNull: true, type: "varchar", params: { length: 32 } }, entity: { + notNull: true, type: "varchar", params: { length: 32 } }, entityId: { + notNull: true, type: "varchar", params: { length: 64 } }, action: { + notNull: true, type: "varchar", params: { length: 16 } }, data: { + notNull: true, type: "object" }, filter: { diff --git a/lib/base-app-domain/ModiEntity/Storage.js b/lib/base-app-domain/ModiEntity/Storage.js index 7b8a078..eee9ae2 100644 --- a/lib/base-app-domain/ModiEntity/Storage.js +++ b/lib/base-app-domain/ModiEntity/Storage.js @@ -5,10 +5,12 @@ var action_1 = require("../../actions/action"); exports.desc = { attributes: { modiId: { + notNull: true, type: "ref", ref: "modi" }, entity: { + notNull: true, type: "varchar", params: { length: 32 @@ -16,6 +18,7 @@ exports.desc = { ref: ["user", "userEntityGrant"] }, entityId: { + notNull: true, type: "varchar", params: { length: 64 diff --git a/lib/base-app-domain/Oper/Storage.js b/lib/base-app-domain/Oper/Storage.js index a440ae5..344d8d2 100644 --- a/lib/base-app-domain/Oper/Storage.js +++ b/lib/base-app-domain/Oper/Storage.js @@ -5,12 +5,14 @@ var action_1 = require("../../actions/action"); exports.desc = { attributes: { action: { + notNull: true, type: "varchar", params: { length: 16 } }, data: { + notNull: true, type: "object" }, filter: { @@ -24,6 +26,7 @@ exports.desc = { ref: "user" }, targetEntity: { + notNull: true, type: "varchar", params: { length: 32 diff --git a/lib/base-app-domain/OperEntity/Storage.js b/lib/base-app-domain/OperEntity/Storage.js index 2ee6a26..3421012 100644 --- a/lib/base-app-domain/OperEntity/Storage.js +++ b/lib/base-app-domain/OperEntity/Storage.js @@ -5,10 +5,12 @@ var action_1 = require("../../actions/action"); exports.desc = { attributes: { operId: { + notNull: true, type: "ref", ref: "oper" }, entity: { + notNull: true, type: "varchar", params: { length: 32 @@ -16,6 +18,7 @@ exports.desc = { ref: ["user", "userEntityGrant"] }, entityId: { + notNull: true, type: "varchar", params: { length: 64 diff --git a/lib/base-app-domain/UserEntityGrant/Storage.js b/lib/base-app-domain/UserEntityGrant/Storage.js index 952b3bd..68fbcf7 100644 --- a/lib/base-app-domain/UserEntityGrant/Storage.js +++ b/lib/base-app-domain/UserEntityGrant/Storage.js @@ -5,18 +5,21 @@ var action_1 = require("../../actions/action"); exports.desc = { attributes: { entity: { + notNull: true, type: "varchar", params: { length: 32 } }, entityId: { + notNull: true, type: "varchar", params: { length: 64 } }, relation: { + notNull: true, type: "varchar", params: { length: 32 diff --git a/lib/checkers/index.js b/lib/checkers/index.js index 4ef4b19..b679393 100644 --- a/lib/checkers/index.js +++ b/lib/checkers/index.js @@ -8,6 +8,7 @@ function createDynamicCheckers(schema, authDict) { var checkers = []; checkers.push.apply(checkers, tslib_1.__spreadArray([], tslib_1.__read((0, modi_1.createModiRelatedCheckers)(schema)), false)); checkers.push.apply(checkers, tslib_1.__spreadArray([], tslib_1.__read((0, checker_1.createRemoveCheckers)(schema, authDict)), false)); + checkers.push.apply(checkers, tslib_1.__spreadArray([], tslib_1.__read((0, checker_1.createCreateCheckers)(schema)), false)); if (authDict) { checkers.push.apply(checkers, tslib_1.__spreadArray([], tslib_1.__read((0, checker_1.createAuthCheckers)(schema, authDict)), false)); } diff --git a/lib/compiler/schemalBuilder.js b/lib/compiler/schemalBuilder.js index 2ce4d2d..e33febd 100644 --- a/lib/compiler/schemalBuilder.js +++ b/lib/compiler/schemalBuilder.js @@ -2917,7 +2917,10 @@ function constructAttributes(entity) { var result = []; schemaAttrs.forEach(function (attr) { var attrAssignments = []; - var name = attr.name, type = attr.type; + var name = attr.name, type = attr.type, allowNull = attr.questionToken; + if (!allowNull) { + attrAssignments.push(factory.createPropertyAssignment(factory.createIdentifier("notNull"), factory.createTrue())); + } var name2 = name; if (ts.isTypeReferenceNode(type)) { var typeName = type.typeName, typeArguments = type.typeArguments; diff --git a/lib/store/checker.d.ts b/lib/store/checker.d.ts index 7aa7e0c..0c7772a 100644 --- a/lib/store/checker.d.ts +++ b/lib/store/checker.d.ts @@ -30,3 +30,4 @@ export declare function createAuthCheckers | SyncContext>(schema: StorageSchema, authDict?: AuthDefDict): Checker[]; +export declare function createCreateCheckers | SyncContext>(schema: StorageSchema): Checker[]; diff --git a/lib/store/checker.js b/lib/store/checker.js index 550fe04..07a63ee 100644 --- a/lib/store/checker.js +++ b/lib/store/checker.js @@ -1,6 +1,6 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.createRemoveCheckers = exports.createAuthCheckers = exports.translateCheckerInSyncContext = exports.translateCheckerInAsyncContext = void 0; +exports.createCreateCheckers = exports.createRemoveCheckers = exports.createAuthCheckers = exports.translateCheckerInSyncContext = exports.translateCheckerInAsyncContext = void 0; var tslib_1 = require("tslib"); var assert_1 = tslib_1.__importDefault(require("assert")); var filter_1 = require("../store/filter"); @@ -1216,3 +1216,69 @@ function createRemoveCheckers(schema, authDict) { return checkers; } exports.createRemoveCheckers = createRemoveCheckers; +function createCreateCheckers(schema) { + var checkers = []; + var _loop_9 = function (entity) { + var attributes = schema[entity].attributes; + var notNullAttrs = Object.keys(attributes).filter(function (ele) { return attributes[ele].notNull; }); + checkers.push({ + entity: entity, + type: 'data', + action: 'create', + checker: function (data) { + var illegalNullAttrs = (0, lodash_1.difference)(notNullAttrs, Object.keys(data)); + if (illegalNullAttrs.length > 0) { + throw new Exception_1.OakAttrNotNullException(entity, illegalNullAttrs); + } + for (var attr in data) { + if (attributes[attr]) { + var _a = attributes[attr], type = _a.type, params = _a.params, defaultValue = _a.default, enumeration = _a.enumeration; + switch (type) { + case 'char': + case 'varchar': { + if (typeof data[attr] !== 'string') { + throw new Exception_1.OakInputIllegalException(entity, [attr], 'not a string'); + } + var length_1 = params.length; + if (length_1 && data[attr].length > length_1) { + throw new Exception_1.OakInputIllegalException(entity, [attr], 'too long'); + } + break; + } + case 'int': + case 'smallint': + case 'tinyint': + case 'bigint': + case 'decimal': + case 'money': { + if (typeof data[attr] !== 'number') { + throw new Exception_1.OakInputIllegalException(entity, [attr], 'not a number'); + } + var _b = params, min = _b.min, max = _b.max; + if (typeof min === 'number' && data[attr] < min) { + throw new Exception_1.OakInputIllegalException(entity, [attr], 'too small'); + } + if (typeof max === 'number' && data[attr] > max) { + throw new Exception_1.OakInputIllegalException(entity, [attr], 'too big'); + } + break; + } + case 'enum': { + (0, assert_1.default)(enumeration); + if (!enumeration.includes(data[attr])) { + throw new Exception_1.OakInputIllegalException(entity, [attr], 'not in enumberation'); + } + break; + } + } + } + } + } + }); + }; + for (var entity in schema) { + _loop_9(entity); + } + return checkers; +} +exports.createCreateCheckers = createCreateCheckers; diff --git a/lib/types/Exception.d.ts b/lib/types/Exception.d.ts index a0c875a..4907711 100644 --- a/lib/types/Exception.d.ts +++ b/lib/types/Exception.d.ts @@ -55,12 +55,15 @@ export declare class OakRowInconsistencyException extends export declare class OakInputIllegalException extends OakUserException { private attributes; private entity; - constructor(entity: string, attributes: string[], message?: string); - getEntity(): string; + constructor(entity: keyof ED, attributes: string[], message?: string); + getEntity(): keyof ED; getAttributes(): string[]; addAttributesPrefix(prefix: string): void; toString(): string; } +export declare class OakAttrNotNullException extends OakInputIllegalException { + constructor(entity: keyof ED, attributes: string[], message?: string); +} /** * 用户权限不够时抛的异常 */ diff --git a/lib/types/Exception.js b/lib/types/Exception.js index ecfeaee..bcb5af1 100644 --- a/lib/types/Exception.js +++ b/lib/types/Exception.js @@ -1,6 +1,6 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.makeException = exports.OakPreConditionUnsetException = exports.OakDeadlock = exports.OakCongruentRowExists = exports.OakRowLockedException = exports.OakUnloggedInException = exports.OakUserUnpermittedException = exports.OakInputIllegalException = exports.OakRowInconsistencyException = exports.OakUserException = exports.OakExternalException = exports.OakRowUnexistedException = exports.OakOperExistedException = exports.OakImportDataParseException = exports.OakUniqueViolationException = exports.OakDataException = exports.OakException = void 0; +exports.makeException = exports.OakPreConditionUnsetException = exports.OakDeadlock = exports.OakCongruentRowExists = exports.OakRowLockedException = exports.OakUnloggedInException = exports.OakUserUnpermittedException = exports.OakAttrNotNullException = exports.OakInputIllegalException = exports.OakRowInconsistencyException = exports.OakUserException = exports.OakExternalException = exports.OakRowUnexistedException = exports.OakOperExistedException = exports.OakImportDataParseException = exports.OakUniqueViolationException = exports.OakDataException = exports.OakException = void 0; var tslib_1 = require("tslib"); var assert_1 = tslib_1.__importDefault(require("assert")); var OakException = /** @class */ (function (_super) { @@ -179,6 +179,15 @@ var OakInputIllegalException = /** @class */ (function (_super) { }(OakUserException)); exports.OakInputIllegalException = OakInputIllegalException; ; +// 属性为空 +var OakAttrNotNullException = /** @class */ (function (_super) { + tslib_1.__extends(OakAttrNotNullException, _super); + function OakAttrNotNullException(entity, attributes, message) { + return _super.call(this, entity, attributes, message || '属性不允许为空') || this; + } + return OakAttrNotNullException; +}(OakInputIllegalException)); +exports.OakAttrNotNullException = OakAttrNotNullException; /** * 用户权限不够时抛的异常 */ diff --git a/lib/utils/validator.js b/lib/utils/validator.js index 746ac13..25cfe1c 100644 --- a/lib/utils/validator.js +++ b/lib/utils/validator.js @@ -114,7 +114,7 @@ function checkAttributesNotNull(entity, data, attributes, allowEmpty) { } }); if (attrs.length > 0) { - throw new types_1.OakInputIllegalException(entity, attrs, '属性不能为空'); + throw new types_1.OakAttrNotNullException(entity, attrs, '属性不能为空'); } } exports.checkAttributesNotNull = checkAttributesNotNull; diff --git a/src/checkers/index.ts b/src/checkers/index.ts index 840ce8b..10acf66 100644 --- a/src/checkers/index.ts +++ b/src/checkers/index.ts @@ -1,6 +1,6 @@ import { EntityDict } from '../base-app-domain'; import { AsyncContext } from '../store/AsyncRowStore'; -import { createAuthCheckers, createRemoveCheckers } from '../store/checker'; +import { createAuthCheckers, createRemoveCheckers, createCreateCheckers } from '../store/checker'; import { createModiRelatedCheckers } from '../store/modi'; import { SyncContext } from '../store/SyncRowStore'; import { StorageSchema, EntityDict as BaseEntityDict, Checker, AuthDef, AuthDefDict } from '../types'; @@ -9,6 +9,7 @@ export function createDynamicCheckers[] = []; checkers.push(...createModiRelatedCheckers(schema)); checkers.push(...createRemoveCheckers(schema, authDict)); + checkers.push(...createCreateCheckers(schema)); if (authDict) { checkers.push(...createAuthCheckers(schema, authDict)); } diff --git a/src/compiler/schemalBuilder.ts b/src/compiler/schemalBuilder.ts index 94db06f..060f53e 100644 --- a/src/compiler/schemalBuilder.ts +++ b/src/compiler/schemalBuilder.ts @@ -5268,7 +5268,15 @@ function constructAttributes(entity: string): ts.PropertyAssignment[] { schemaAttrs.forEach( (attr) => { const attrAssignments: ts.PropertyAssignment[] = []; - const { name, type } = attr; + const { name, type, questionToken: allowNull } = attr; + if (!allowNull) { + attrAssignments.push( + factory.createPropertyAssignment( + factory.createIdentifier("notNull"), + factory.createTrue(), + ), + ); + } let name2 = name; if (ts.isTypeReferenceNode(type!)) { diff --git a/src/store/checker.ts b/src/store/checker.ts index 2efede7..ccf2615 100644 --- a/src/store/checker.ts +++ b/src/store/checker.ts @@ -1,6 +1,6 @@ import assert from 'assert'; import { addFilterSegment, checkFilterContains, combineFilters } from "../store/filter"; -import { OakRowInconsistencyException, OakUserUnpermittedException } from '../types/Exception'; +import { OakAttrNotNullException, OakInputIllegalException, OakRowInconsistencyException, OakUserUnpermittedException } from '../types/Exception'; import { AuthDefDict, CascadeRelationItem, Checker, CreateTriggerInTxn, EntityDict, OperateOption, SelectOption, StorageSchema, Trigger, UpdateTriggerInTxn, RelationHierarchy, SelectOpResult, REMOVE_CASCADE_PRIORITY, RefOrExpression, SyncOrAsync @@ -777,10 +777,10 @@ export function createAuthCheckers | SyncContext>(schema: StorageSchema) { + const checkers: Checker[] = []; + + for (const entity in schema) { + const { attributes } = schema[entity]; + const notNullAttrs = Object.keys(attributes).filter( + ele => attributes[ele].notNull + ); + + checkers.push({ + entity, + type: 'data', + action: 'create' as ED[keyof ED]['Action'], + checker: (data) => { + const illegalNullAttrs = difference(notNullAttrs, Object.keys(data)); + if (illegalNullAttrs.length > 0) { + throw new OakAttrNotNullException(entity, illegalNullAttrs); + } + for (const attr in data) { + if (attributes[attr]) { + const { type, params, default: defaultValue, enumeration } = attributes[attr]; + switch (type) { + case 'char': + case 'varchar': { + if (typeof (data as ED[keyof ED]['CreateSingle']['data'])[attr] !== 'string') { + throw new OakInputIllegalException(entity, [attr], 'not a string'); + } + const { length } = params!; + if (length && (data as ED[keyof ED]['CreateSingle']['data'])[attr]!.length > length) { + throw new OakInputIllegalException(entity, [attr], 'too long'); + } + break; + } + case 'int': + case 'smallint': + case 'tinyint': + case 'bigint': + case 'decimal': + case 'money': { + if (typeof (data as ED[keyof ED]['CreateSingle']['data'])[attr] !== 'number') { + throw new OakInputIllegalException(entity, [attr], 'not a number'); + } + const { min, max } = params!; + if (typeof min === 'number' && (data as ED[keyof ED]['CreateSingle']['data'])[attr] < min) { + throw new OakInputIllegalException(entity, [attr], 'too small'); + } + if (typeof max === 'number' && (data as ED[keyof ED]['CreateSingle']['data'])[attr] > max) { + throw new OakInputIllegalException(entity, [attr], 'too big'); + } + break; + } + case 'enum': { + assert(enumeration); + if (!enumeration.includes((data as ED[keyof ED]['CreateSingle']['data'])[attr])) { + throw new OakInputIllegalException(entity, [attr], 'not in enumberation'); + } + break; + } + } + } + } + } + }) + } + return checkers; } \ No newline at end of file diff --git a/src/types/Exception.ts b/src/types/Exception.ts index 69bcbec..d00722f 100644 --- a/src/types/Exception.ts +++ b/src/types/Exception.ts @@ -138,8 +138,8 @@ export class OakRowInconsistencyException extends OakUser */ export class OakInputIllegalException extends OakUserException { private attributes: string[]; - private entity: string; - constructor(entity: string, attributes: string[], message?: string) { + private entity: keyof ED; + constructor(entity: keyof ED, attributes: string[], message?: string) { super(message); this.entity = entity; this.attributes = attributes; @@ -169,6 +169,13 @@ export class OakInputIllegalException extends OakUserExce } }; +// 属性为空 +export class OakAttrNotNullException extends OakInputIllegalException { + constructor(entity: keyof ED, attributes: string[], message?: string) { + super(entity, attributes, message || '属性不允许为空'); + } +} + /** * 用户权限不够时抛的异常 */ diff --git a/src/utils/validator.ts b/src/utils/validator.ts index 34bd97f..5ce1ce5 100644 --- a/src/utils/validator.ts +++ b/src/utils/validator.ts @@ -3,7 +3,7 @@ */ 'use strict'; -import { EntityDict, OakInputIllegalException } from "../types"; +import { EntityDict, OakAttrNotNullException, OakInputIllegalException } from "../types"; type ValidatorFunction = (text: string, size?:number) => string|boolean; type ValidatorMoneyFunction = (text: string, zero?:boolean) => string|boolean; @@ -129,7 +129,7 @@ export function checkAttributesNotNull 0) { - throw new OakInputIllegalException(entity as string, attrs, '属性不能为空'); + throw new OakAttrNotNullException(entity as string, attrs, '属性不能为空'); } }; From 30f2585cf25fcd447f53d5f86dcd92feeac41fc0 Mon Sep 17 00:00:00 2001 From: "Xc@centOs" Date: Mon, 3 Apr 2023 15:18:53 +0800 Subject: [PATCH 03/10] =?UTF-8?q?=E4=B8=A4=E4=B8=AA=E5=B0=8F=E7=AC=94?= =?UTF-8?q?=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/store/checker.js | 88 +++++++++++++++++++++++-------------------- lib/timers/vaccum.js | 8 ++-- src/store/checker.ts | 90 ++++++++++++++++++++++++-------------------- src/timers/vaccum.ts | 4 +- 4 files changed, 104 insertions(+), 86 deletions(-) diff --git a/lib/store/checker.js b/lib/store/checker.js index 07a63ee..b059dc8 100644 --- a/lib/store/checker.js +++ b/lib/store/checker.js @@ -1226,52 +1226,60 @@ function createCreateCheckers(schema) { type: 'data', action: 'create', checker: function (data) { - var illegalNullAttrs = (0, lodash_1.difference)(notNullAttrs, Object.keys(data)); - if (illegalNullAttrs.length > 0) { - throw new Exception_1.OakAttrNotNullException(entity, illegalNullAttrs); - } - for (var attr in data) { - if (attributes[attr]) { - var _a = attributes[attr], type = _a.type, params = _a.params, defaultValue = _a.default, enumeration = _a.enumeration; - switch (type) { - case 'char': - case 'varchar': { - if (typeof data[attr] !== 'string') { - throw new Exception_1.OakInputIllegalException(entity, [attr], 'not a string'); + var checkData = function (data2) { + var illegalNullAttrs = (0, lodash_1.difference)(notNullAttrs, Object.keys(data2)); + if (illegalNullAttrs.length > 0) { + throw new Exception_1.OakAttrNotNullException(entity, illegalNullAttrs); + } + for (var attr in data2) { + if (attributes[attr]) { + var _a = attributes[attr], type = _a.type, params = _a.params, defaultValue = _a.default, enumeration = _a.enumeration; + switch (type) { + case 'char': + case 'varchar': { + if (typeof data2[attr] !== 'string') { + throw new Exception_1.OakInputIllegalException(entity, [attr], 'not a string'); + } + var length_1 = params.length; + if (length_1 && data2[attr].length > length_1) { + throw new Exception_1.OakInputIllegalException(entity, [attr], 'too long'); + } + break; } - var length_1 = params.length; - if (length_1 && data[attr].length > length_1) { - throw new Exception_1.OakInputIllegalException(entity, [attr], 'too long'); + case 'int': + case 'smallint': + case 'tinyint': + case 'bigint': + case 'decimal': + case 'money': { + if (typeof data2[attr] !== 'number') { + throw new Exception_1.OakInputIllegalException(entity, [attr], 'not a number'); + } + var _b = params, min = _b.min, max = _b.max; + if (typeof min === 'number' && data2[attr] < min) { + throw new Exception_1.OakInputIllegalException(entity, [attr], 'too small'); + } + if (typeof max === 'number' && data2[attr] > max) { + throw new Exception_1.OakInputIllegalException(entity, [attr], 'too big'); + } + break; } - break; - } - case 'int': - case 'smallint': - case 'tinyint': - case 'bigint': - case 'decimal': - case 'money': { - if (typeof data[attr] !== 'number') { - throw new Exception_1.OakInputIllegalException(entity, [attr], 'not a number'); + case 'enum': { + (0, assert_1.default)(enumeration); + if (!enumeration.includes(data2[attr])) { + throw new Exception_1.OakInputIllegalException(entity, [attr], 'not in enumberation'); + } + break; } - var _b = params, min = _b.min, max = _b.max; - if (typeof min === 'number' && data[attr] < min) { - throw new Exception_1.OakInputIllegalException(entity, [attr], 'too small'); - } - if (typeof max === 'number' && data[attr] > max) { - throw new Exception_1.OakInputIllegalException(entity, [attr], 'too big'); - } - break; - } - case 'enum': { - (0, assert_1.default)(enumeration); - if (!enumeration.includes(data[attr])) { - throw new Exception_1.OakInputIllegalException(entity, [attr], 'not in enumberation'); - } - break; } } } + }; + if (data instanceof Array) { + data.forEach(function (ele) { return checkData(ele); }); + } + else { + checkData(data); } } }); diff --git a/lib/timers/vaccum.js b/lib/timers/vaccum.js index 8d68731..fcbf533 100644 --- a/lib/timers/vaccum.js +++ b/lib/timers/vaccum.js @@ -5,7 +5,6 @@ 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"); /** @@ -23,7 +22,7 @@ function vaccumEntities(option, context) { 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 entity, filter, aliveLine, filter2, zip, now, backFile, fd_1, attributes_1, projection_1, attr, count_1, appendData_1, createGzip, gzip_1, source_1, destination_1, _c, _d, _e; var _f, _g; return tslib_1.__generator(this, function (_h) { switch (_h.label) { @@ -37,7 +36,7 @@ function vaccumEntities(option, context) { if (filter) { filter2 = (0, filter_1.combineFilters)([filter2, filter]); } - if (!backupDir) return [3 /*break*/, 4]; + if (!(backupDir && process.env.OAK_PLATFORM === 'server')) 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"); @@ -107,7 +106,8 @@ function vaccumEntities(option, context) { return [3 /*break*/, 4]; case 2: if (!zip) return [3 /*break*/, 4]; - gzip_1 = (0, node_zlib_1.createGzip)(); + createGzip = require('zlib').createGzip; + gzip_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) { diff --git a/src/store/checker.ts b/src/store/checker.ts index ccf2615..360796b 100644 --- a/src/store/checker.ts +++ b/src/store/checker.ts @@ -1184,52 +1184,62 @@ export function createCreateCheckers { - const illegalNullAttrs = difference(notNullAttrs, Object.keys(data)); - if (illegalNullAttrs.length > 0) { - throw new OakAttrNotNullException(entity, illegalNullAttrs); - } - for (const attr in data) { - if (attributes[attr]) { - const { type, params, default: defaultValue, enumeration } = attributes[attr]; - switch (type) { - case 'char': - case 'varchar': { - if (typeof (data as ED[keyof ED]['CreateSingle']['data'])[attr] !== 'string') { - throw new OakInputIllegalException(entity, [attr], 'not a string'); + const checkData = (data2: ED[keyof ED]['CreateSingle']['data']) => { + const illegalNullAttrs = difference(notNullAttrs, Object.keys(data2)); + if (illegalNullAttrs.length > 0) { + throw new OakAttrNotNullException(entity, illegalNullAttrs); + } + for (const attr in data2) { + if (attributes[attr as string]) { + const { type, params, default: defaultValue, enumeration } = attributes[attr as string]; + switch (type) { + case 'char': + case 'varchar': { + if (typeof (data2 as ED[keyof ED]['CreateSingle']['data'])[attr] !== 'string') { + throw new OakInputIllegalException(entity, [attr], 'not a string'); + } + const { length } = params!; + if (length && (data2 as ED[keyof ED]['CreateSingle']['data'])[attr]!.length > length) { + throw new OakInputIllegalException(entity, [attr], 'too long'); + } + break; } - const { length } = params!; - if (length && (data as ED[keyof ED]['CreateSingle']['data'])[attr]!.length > length) { - throw new OakInputIllegalException(entity, [attr], 'too long'); + case 'int': + case 'smallint': + case 'tinyint': + case 'bigint': + case 'decimal': + case 'money': { + if (typeof (data2 as ED[keyof ED]['CreateSingle']['data'])[attr] !== 'number') { + throw new OakInputIllegalException(entity, [attr], 'not a number'); + } + const { min, max } = params!; + if (typeof min === 'number' && (data2 as ED[keyof ED]['CreateSingle']['data'])[attr] < min) { + throw new OakInputIllegalException(entity, [attr], 'too small'); + } + if (typeof max === 'number' && (data2 as ED[keyof ED]['CreateSingle']['data'])[attr] > max) { + throw new OakInputIllegalException(entity, [attr], 'too big'); + } + break; } - break; - } - case 'int': - case 'smallint': - case 'tinyint': - case 'bigint': - case 'decimal': - case 'money': { - if (typeof (data as ED[keyof ED]['CreateSingle']['data'])[attr] !== 'number') { - throw new OakInputIllegalException(entity, [attr], 'not a number'); + case 'enum': { + assert(enumeration); + if (!enumeration.includes((data2 as ED[keyof ED]['CreateSingle']['data'])[attr])) { + throw new OakInputIllegalException(entity, [attr], 'not in enumberation'); + } + break; } - const { min, max } = params!; - if (typeof min === 'number' && (data as ED[keyof ED]['CreateSingle']['data'])[attr] < min) { - throw new OakInputIllegalException(entity, [attr], 'too small'); - } - if (typeof max === 'number' && (data as ED[keyof ED]['CreateSingle']['data'])[attr] > max) { - throw new OakInputIllegalException(entity, [attr], 'too big'); - } - break; - } - case 'enum': { - assert(enumeration); - if (!enumeration.includes((data as ED[keyof ED]['CreateSingle']['data'])[attr])) { - throw new OakInputIllegalException(entity, [attr], 'not in enumberation'); - } - break; } } } + }; + if (data instanceof Array) { + data.forEach( + ele => checkData(ele) + ); + } + else { + checkData(data as ED[keyof ED]['CreateSingle']['data']); } } }) diff --git a/src/timers/vaccum.ts b/src/timers/vaccum.ts index cac0f6e..00fb74b 100644 --- a/src/timers/vaccum.ts +++ b/src/timers/vaccum.ts @@ -4,7 +4,6 @@ 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'; @@ -38,7 +37,7 @@ export async function vaccumEntities Date: Wed, 5 Apr 2023 14:12:38 +0800 Subject: [PATCH 04/10] =?UTF-8?q?=E4=B8=80=E4=B8=AA=E5=B0=8F=E7=9A=84?= =?UTF-8?q?=E5=A3=B0=E6=98=8E=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/store/TriggerExecutor.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/store/TriggerExecutor.ts b/src/store/TriggerExecutor.ts index 3b7c726..ce092ca 100644 --- a/src/store/TriggerExecutor.ts +++ b/src/store/TriggerExecutor.ts @@ -241,7 +241,7 @@ export class TriggerExecutor { } } const number = (trigger as CreateTrigger).fn({ operation: operation as ED[T]['Create'] }, context, option as OperateOption); - if (number > 0) { + if (number as number > 0) { this.logger.info(`触发器「${trigger.name}」成功触发了「${number}」行数据更改`); } } @@ -371,7 +371,7 @@ export class TriggerExecutor { operation: operation as ED[T]['Selection'], result: result!, }, context, option as SelectOption); - if (number > 0) { + if (number as number > 0) { this.logger.info(`触发器「${trigger.name}」成功触发了「${number}」行数据更改`); } } From 1406effce5fb2175c649e96a35f68f05d842dd4f Mon Sep 17 00:00:00 2001 From: "Xc@centOs" Date: Mon, 10 Apr 2023 15:28:21 +0800 Subject: [PATCH 05/10] =?UTF-8?q?=E5=AF=BC=E5=87=BA=E4=BA=86Schema?= =?UTF-8?q?=E4=BE=9B=E5=A4=96=E5=B1=82=E5=BC=95=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/types/Entity.d.ts | 2 +- src/types/Entity.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/types/Entity.d.ts b/lib/types/Entity.d.ts index 99255df..bb3642f 100644 --- a/lib/types/Entity.d.ts +++ b/lib/types/Entity.d.ts @@ -65,7 +65,7 @@ export interface EntityShape { $$updateAt$$: number | Date; $$deleteAt$$?: number | Date | null; } -interface GeneralEntityShape extends EntityShape { +export interface GeneralEntityShape extends EntityShape { [K: string]: any; } export declare type MakeAction = A; diff --git a/src/types/Entity.ts b/src/types/Entity.ts index 35f1ff3..9dafc79 100644 --- a/src/types/Entity.ts +++ b/src/types/Entity.ts @@ -81,7 +81,7 @@ export interface EntityShape { $$deleteAt$$?: number | Date | null; } -interface GeneralEntityShape extends EntityShape { +export interface GeneralEntityShape extends EntityShape { [K: string]: any; } From b5089af98329a0f79e2810f616fe8a92d3313d76 Mon Sep 17 00:00:00 2001 From: "Xc@centOs" Date: Wed, 12 Apr 2023 15:43:48 +0800 Subject: [PATCH 06/10] =?UTF-8?q?checker=E4=B8=AD=E7=9A=84=E5=B0=8F?= =?UTF-8?q?=E7=AC=94=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/store/checker.js | 2 +- src/store/checker.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/store/checker.js b/lib/store/checker.js index b059dc8..a5e20ff 100644 --- a/lib/store/checker.js +++ b/lib/store/checker.js @@ -1255,7 +1255,7 @@ function createCreateCheckers(schema) { if (typeof data2[attr] !== 'number') { throw new Exception_1.OakInputIllegalException(entity, [attr], 'not a number'); } - var _b = params, min = _b.min, max = _b.max; + var _b = params || {}, min = _b.min, max = _b.max; if (typeof min === 'number' && data2[attr] < min) { throw new Exception_1.OakInputIllegalException(entity, [attr], 'too small'); } diff --git a/src/store/checker.ts b/src/store/checker.ts index 360796b..0d78d5e 100644 --- a/src/store/checker.ts +++ b/src/store/checker.ts @@ -1213,7 +1213,7 @@ export function createCreateCheckers Date: Wed, 12 Apr 2023 16:14:56 +0800 Subject: [PATCH 07/10] =?UTF-8?q?=E5=9C=A8create=E6=97=B6=E6=A3=80?= =?UTF-8?q?=E6=9F=A5not=20null=E6=97=B6=E5=A4=84=E7=90=86=E4=BA=86cascade?= =?UTF-8?q?=20create?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/store/checker.js | 54 ++++++++++++++++++++++++++++++++++++++++--- lib/store/relation.js | 1 + src/store/checker.ts | 29 ++++++++++++++++++++++- src/store/relation.ts | 1 + 4 files changed, 81 insertions(+), 4 deletions(-) diff --git a/lib/store/checker.js b/lib/store/checker.js index a5e20ff..6568568 100644 --- a/lib/store/checker.js +++ b/lib/store/checker.js @@ -1227,13 +1227,61 @@ function createCreateCheckers(schema) { action: 'create', checker: function (data) { var checkData = function (data2) { + var e_9, _a, e_10, _b; var illegalNullAttrs = (0, lodash_1.difference)(notNullAttrs, Object.keys(data2)); if (illegalNullAttrs.length > 0) { - throw new Exception_1.OakAttrNotNullException(entity, illegalNullAttrs); + try { + // 要处理多对一的cascade create + for (var illegalNullAttrs_1 = (e_9 = void 0, tslib_1.__values(illegalNullAttrs)), illegalNullAttrs_1_1 = illegalNullAttrs_1.next(); !illegalNullAttrs_1_1.done; illegalNullAttrs_1_1 = illegalNullAttrs_1.next()) { + var attr = illegalNullAttrs_1_1.value; + if (attr === 'entityId') { + if (illegalNullAttrs.includes('entity')) { + continue; + } + } + else if (attr === 'entity' && attributes[attr].type === 'ref') { + var hasCascadeCreate = false; + try { + for (var _c = (e_10 = void 0, tslib_1.__values(attributes[attr].ref)), _d = _c.next(); !_d.done; _d = _c.next()) { + var ref = _d.value; + if (data2[ref] && data2[ref].action === 'create') { + hasCascadeCreate = true; + break; + } + } + } + catch (e_10_1) { e_10 = { error: e_10_1 }; } + finally { + try { + if (_d && !_d.done && (_b = _c.return)) _b.call(_c); + } + finally { if (e_10) throw e_10.error; } + } + if (hasCascadeCreate) { + continue; + } + } + else if (attributes[attr].type === 'ref') { + var ref = attributes[attr].ref; + if (data2[ref] && data2[ref].action === 'create') { + continue; + } + } + // 到这里说明确实是有not null的属性没有赋值 + throw new Exception_1.OakAttrNotNullException(entity, illegalNullAttrs); + } + } + catch (e_9_1) { e_9 = { error: e_9_1 }; } + finally { + try { + if (illegalNullAttrs_1_1 && !illegalNullAttrs_1_1.done && (_a = illegalNullAttrs_1.return)) _a.call(illegalNullAttrs_1); + } + finally { if (e_9) throw e_9.error; } + } } for (var attr in data2) { if (attributes[attr]) { - var _a = attributes[attr], type = _a.type, params = _a.params, defaultValue = _a.default, enumeration = _a.enumeration; + var _e = attributes[attr], type = _e.type, params = _e.params, defaultValue = _e.default, enumeration = _e.enumeration; switch (type) { case 'char': case 'varchar': { @@ -1255,7 +1303,7 @@ function createCreateCheckers(schema) { if (typeof data2[attr] !== 'number') { throw new Exception_1.OakInputIllegalException(entity, [attr], 'not a number'); } - var _b = params || {}, min = _b.min, max = _b.max; + var _f = params || {}, min = _f.min, max = _f.max; if (typeof min === 'number' && data2[attr] < min) { throw new Exception_1.OakInputIllegalException(entity, [attr], 'too small'); } diff --git a/lib/store/relation.js b/lib/store/relation.js index 9338ae4..765dc26 100644 --- a/lib/store/relation.js +++ b/lib/store/relation.js @@ -55,6 +55,7 @@ function judgeRelation(schema, entity, attr) { else if (attributes.hasOwnProperty('entity') && attributes.hasOwnProperty('entityId') && schema.hasOwnProperty(attr)) { + (0, assert_1.default)(attributes.entity.ref.includes(attr), '不应当出现的case'); // 反向指针的外键 return 2; } diff --git a/src/store/checker.ts b/src/store/checker.ts index 0d78d5e..955e610 100644 --- a/src/store/checker.ts +++ b/src/store/checker.ts @@ -1187,7 +1187,34 @@ export function createCreateCheckers { const illegalNullAttrs = difference(notNullAttrs, Object.keys(data2)); if (illegalNullAttrs.length > 0) { - throw new OakAttrNotNullException(entity, illegalNullAttrs); + // 要处理多对一的cascade create + for (const attr of illegalNullAttrs) { + if (attr === 'entityId') { + if (illegalNullAttrs.includes('entity')) { + continue; + } + } + else if (attr === 'entity' && attributes[attr].type === 'ref') { + let hasCascadeCreate = false; + for (const ref of attributes[attr].ref as string[]) { + if (data2[ref] && data2[ref].action === 'create') { + hasCascadeCreate = true; + break; + } + } + if (hasCascadeCreate) { + continue; + } + } + else if (attributes[attr].type === 'ref') { + const ref = attributes[attr].ref as string; + if (data2[ref] && data2[ref].action === 'create') { + continue; + } + } + // 到这里说明确实是有not null的属性没有赋值 + throw new OakAttrNotNullException(entity, illegalNullAttrs); + } } for (const attr in data2) { if (attributes[attr as string]) { diff --git a/src/store/relation.ts b/src/store/relation.ts index 7a65389..3723cdd 100644 --- a/src/store/relation.ts +++ b/src/store/relation.ts @@ -59,6 +59,7 @@ export function judgeRelation Date: Wed, 12 Apr 2023 17:49:16 +0800 Subject: [PATCH 08/10] =?UTF-8?q?checker=E4=B8=AD=E5=AF=B9=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=E6=95=B0=E6=8D=AE=E6=A3=80=E6=9F=A5=E7=9A=84=E5=A2=9E?= =?UTF-8?q?=E5=BC=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/store/checker.js | 119 +++++++++++++++++++++++++---------------- src/store/checker.ts | 123 +++++++++++++++++++++++++++---------------- 2 files changed, 154 insertions(+), 88 deletions(-) diff --git a/lib/store/checker.js b/lib/store/checker.js index 6568568..5c95ce9 100644 --- a/lib/store/checker.js +++ b/lib/store/checker.js @@ -11,6 +11,7 @@ var string_1 = require("../utils/string"); var lodash_1 = require("../utils/lodash"); var relation_1 = require("./relation"); var uuid_1 = require("../utils/uuid"); +var action_1 = require("../actions/action"); /** * * @param checker 要翻译的checker @@ -1216,11 +1217,76 @@ function createRemoveCheckers(schema, authDict) { return checkers; } exports.createRemoveCheckers = createRemoveCheckers; +function checkAttributeLegal(schema, entity, data) { + var _a; + var attributes = schema[entity].attributes; + for (var attr in data) { + if (attributes[attr]) { + var _b = attributes[attr], type = _b.type, params = _b.params, defaultValue = _b.default, enumeration = _b.enumeration, notNull = _b.notNull; + if (data[attr] === null || data[attr] === undefined) { + if (notNull && defaultValue === undefined) { + throw new Exception_1.OakAttrNotNullException(entity, [attr]); + } + if (defaultValue !== undefined) { + Object.assign(data, (_a = {}, + _a[attr] = defaultValue, + _a)); + } + continue; + } + switch (type) { + case 'char': + case 'varchar': { + if (typeof data[attr] !== 'string') { + throw new Exception_1.OakInputIllegalException(entity, [attr], 'not a string'); + } + var length_1 = params.length; + if (length_1 && data[attr].length > length_1) { + throw new Exception_1.OakInputIllegalException(entity, [attr], 'too long'); + } + break; + } + case 'int': + case 'smallint': + case 'tinyint': + case 'bigint': + case 'decimal': + case 'money': { + if (typeof data[attr] !== 'number') { + throw new Exception_1.OakInputIllegalException(entity, [attr], 'not a number'); + } + var _c = params || {}, min = _c.min, max = _c.max; + if (typeof min === 'number' && data[attr] < min) { + throw new Exception_1.OakInputIllegalException(entity, [attr], 'too small'); + } + if (typeof max === 'number' && data[attr] > max) { + throw new Exception_1.OakInputIllegalException(entity, [attr], 'too big'); + } + break; + } + case 'enum': { + (0, assert_1.default)(enumeration); + if (!enumeration.includes(data[attr])) { + throw new Exception_1.OakInputIllegalException(entity, [attr], 'not in enumberation'); + } + break; + } + } + } + else { + // 这里似乎还有一种update中带cascade remove的case,等遇到再说(貌似cascadeUpdate没有处理完整这种情况) by Xc + if (typeof data[attr] === 'object' && data[attr].action === 'remove') { + console.warn('cascade remove可能是未处理的边界,请注意'); + } + } + } +} function createCreateCheckers(schema) { var checkers = []; var _loop_9 = function (entity) { - var attributes = schema[entity].attributes; + var _a = schema[entity], attributes = _a.attributes, actions = _a.actions; var notNullAttrs = Object.keys(attributes).filter(function (ele) { return attributes[ele].notNull; }); + var updateActions = (0, lodash_1.difference)(actions, action_1.excludeUpdateActions); checkers.push({ entity: entity, type: 'data', @@ -1279,49 +1345,7 @@ function createCreateCheckers(schema) { finally { if (e_9) throw e_9.error; } } } - for (var attr in data2) { - if (attributes[attr]) { - var _e = attributes[attr], type = _e.type, params = _e.params, defaultValue = _e.default, enumeration = _e.enumeration; - switch (type) { - case 'char': - case 'varchar': { - if (typeof data2[attr] !== 'string') { - throw new Exception_1.OakInputIllegalException(entity, [attr], 'not a string'); - } - var length_1 = params.length; - if (length_1 && data2[attr].length > length_1) { - throw new Exception_1.OakInputIllegalException(entity, [attr], 'too long'); - } - break; - } - case 'int': - case 'smallint': - case 'tinyint': - case 'bigint': - case 'decimal': - case 'money': { - if (typeof data2[attr] !== 'number') { - throw new Exception_1.OakInputIllegalException(entity, [attr], 'not a number'); - } - var _f = params || {}, min = _f.min, max = _f.max; - if (typeof min === 'number' && data2[attr] < min) { - throw new Exception_1.OakInputIllegalException(entity, [attr], 'too small'); - } - if (typeof max === 'number' && data2[attr] > max) { - throw new Exception_1.OakInputIllegalException(entity, [attr], 'too big'); - } - break; - } - case 'enum': { - (0, assert_1.default)(enumeration); - if (!enumeration.includes(data2[attr])) { - throw new Exception_1.OakInputIllegalException(entity, [attr], 'not in enumberation'); - } - break; - } - } - } - } + checkAttributeLegal(schema, entity, data2); }; if (data instanceof Array) { data.forEach(function (ele) { return checkData(ele); }); @@ -1330,6 +1354,13 @@ function createCreateCheckers(schema) { checkData(data); } } + }, { + entity: entity, + type: 'data', + action: updateActions, + checker: function (data) { + checkAttributeLegal(schema, entity, data); + } }); }; for (var entity in schema) { diff --git a/src/store/checker.ts b/src/store/checker.ts index 955e610..486f8fd 100644 --- a/src/store/checker.ts +++ b/src/store/checker.ts @@ -13,6 +13,7 @@ import { firstLetterUpperCase } from '../utils/string'; import { union, uniq, difference } from '../utils/lodash'; import { judgeRelation } from './relation'; import { generateNewId } from '../utils/uuid'; +import { excludeUpdateActions } from '../actions/action'; /** * @@ -1170,15 +1171,84 @@ export function createRemoveCheckers( + schema: StorageSchema, + entity: keyof ED, + data: ED[keyof ED]['Update']['data'] | ED[keyof ED]['CreateSingle']['data']) { + const { attributes } = schema[entity]; + for (const attr in data) { + if (attributes[attr as string]) { + const { type, params, default: defaultValue, enumeration, notNull } = attributes[attr as string]; + if (data[attr] === null || data[attr] === undefined) { + if (notNull && defaultValue === undefined) { + throw new OakAttrNotNullException(entity, [attr]); + } + if (defaultValue !== undefined) { + Object.assign(data, { + [attr]: defaultValue, + }); + } + continue; + } + switch (type) { + case 'char': + case 'varchar': { + if (typeof (data as ED[keyof ED]['CreateSingle']['data'])[attr] !== 'string') { + throw new OakInputIllegalException(entity, [attr], 'not a string'); + } + const { length } = params!; + if (length && (data as ED[keyof ED]['CreateSingle']['data'])[attr]!.length > length) { + throw new OakInputIllegalException(entity, [attr], 'too long'); + } + break; + } + case 'int': + case 'smallint': + case 'tinyint': + case 'bigint': + case 'decimal': + case 'money': { + if (typeof (data as ED[keyof ED]['CreateSingle']['data'])[attr] !== 'number') { + throw new OakInputIllegalException(entity, [attr], 'not a number'); + } + const { min, max } = params || {}; + if (typeof min === 'number' && (data as ED[keyof ED]['CreateSingle']['data'])[attr] < min) { + throw new OakInputIllegalException(entity, [attr], 'too small'); + } + if (typeof max === 'number' && (data as ED[keyof ED]['CreateSingle']['data'])[attr] > max) { + throw new OakInputIllegalException(entity, [attr], 'too big'); + } + break; + } + case 'enum': { + assert(enumeration); + if (!enumeration.includes((data as ED[keyof ED]['CreateSingle']['data'])[attr])) { + throw new OakInputIllegalException(entity, [attr], 'not in enumberation'); + } + break; + } + } + } + else { + // 这里似乎还有一种update中带cascade remove的case,等遇到再说(貌似cascadeUpdate没有处理完整这种情况) by Xc + if (typeof data[attr] === 'object' && data[attr].action === 'remove') { + console.warn('cascade remove可能是未处理的边界,请注意'); + } + } + } +} + export function createCreateCheckers | SyncContext>(schema: StorageSchema) { const checkers: Checker[] = []; for (const entity in schema) { - const { attributes } = schema[entity]; + const { attributes, actions } = schema[entity]; const notNullAttrs = Object.keys(attributes).filter( ele => attributes[ele].notNull ); + const updateActions = difference(actions, excludeUpdateActions); + checkers.push({ entity, type: 'data', @@ -1216,49 +1286,7 @@ export function createCreateCheckers length) { - throw new OakInputIllegalException(entity, [attr], 'too long'); - } - break; - } - case 'int': - case 'smallint': - case 'tinyint': - case 'bigint': - case 'decimal': - case 'money': { - if (typeof (data2 as ED[keyof ED]['CreateSingle']['data'])[attr] !== 'number') { - throw new OakInputIllegalException(entity, [attr], 'not a number'); - } - const { min, max } = params || {}; - if (typeof min === 'number' && (data2 as ED[keyof ED]['CreateSingle']['data'])[attr] < min) { - throw new OakInputIllegalException(entity, [attr], 'too small'); - } - if (typeof max === 'number' && (data2 as ED[keyof ED]['CreateSingle']['data'])[attr] > max) { - throw new OakInputIllegalException(entity, [attr], 'too big'); - } - break; - } - case 'enum': { - assert(enumeration); - if (!enumeration.includes((data2 as ED[keyof ED]['CreateSingle']['data'])[attr])) { - throw new OakInputIllegalException(entity, [attr], 'not in enumberation'); - } - break; - } - } - } - } + checkAttributeLegal(schema, entity, data2); }; if (data instanceof Array) { data.forEach( @@ -1269,6 +1297,13 @@ export function createCreateCheckers { + checkAttributeLegal(schema, entity, data); + } }) } From 3363382898db03283791937e5dc4cee4a9a0adfa Mon Sep 17 00:00:00 2001 From: "Xc@centOs" Date: Wed, 12 Apr 2023 22:03:01 +0800 Subject: [PATCH 09/10] =?UTF-8?q?modi=E7=9A=84=E4=B8=80=E4=B8=AA=E8=A7=A6?= =?UTF-8?q?=E5=8F=91=E5=99=A8=E7=9A=84=E6=9D=A1=E4=BB=B6=E6=9C=89=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/store/modi.js | 4 ++-- src/store/modi.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/store/modi.js b/lib/store/modi.js index c7e53db..381824b 100644 --- a/lib/store/modi.js +++ b/lib/store/modi.js @@ -151,8 +151,8 @@ function createModiRelatedTriggers(schema) { var _this = this; var triggers = []; var _loop_2 = function (entity) { - var inModi = schema[entity].inModi; - if (inModi) { + var toModi = schema[entity].toModi; + if (toModi) { // 当关联modi的对象被删除时,对应的modi也删除。这里似乎只需要删除掉活跃对象?因为oper不能删除,所以oper和modi是必须要支持对deleted对象的容错? // 这里没有想清楚,by Xc 20230209 triggers.push({ diff --git a/src/store/modi.ts b/src/store/modi.ts index 2fe1233..338c5cc 100644 --- a/src/store/modi.ts +++ b/src/store/modi.ts @@ -149,8 +149,8 @@ export function createModiRelatedTriggers[] = []; for (const entity in schema) { - const { inModi } = schema[entity]; - if (inModi) { + const { toModi } = schema[entity]; + if (toModi) { // 当关联modi的对象被删除时,对应的modi也删除。这里似乎只需要删除掉活跃对象?因为oper不能删除,所以oper和modi是必须要支持对deleted对象的容错? // 这里没有想清楚,by Xc 20230209 triggers.push({ From a36d82e3ddcf8a04f31cb1da33764451f12f6612 Mon Sep 17 00:00:00 2001 From: wkj <278599135@qq.com> Date: Fri, 14 Apr 2023 14:26:04 +0800 Subject: [PATCH 10/10] OakAttrNotNullException --- lib/types/Exception.js | 5 +++++ src/types/Exception.ts | 9 +++++++++ 2 files changed, 14 insertions(+) diff --git a/lib/types/Exception.js b/lib/types/Exception.js index bcb5af1..83a3dd8 100644 --- a/lib/types/Exception.js +++ b/lib/types/Exception.js @@ -353,6 +353,11 @@ function makeException(data) { e.setOpRecords(data.opRecords); return e; } + case 'OakAttrNotNullException': { + var e = new OakAttrNotNullException(data.entity, data.attributes, data.message); + e.setOpRecords(data.opRecords); + return e; + } default: return; } diff --git a/src/types/Exception.ts b/src/types/Exception.ts index d00722f..326e0d2 100644 --- a/src/types/Exception.ts +++ b/src/types/Exception.ts @@ -336,6 +336,15 @@ export function makeException(data: { e.setOpRecords(data.opRecords); return e; } + case 'OakAttrNotNullException': { + const e = new OakAttrNotNullException( + data.entity, + data.attributes, + data.message + ); + e.setOpRecords(data.opRecords); + return e; + } default: return; }