Comparing version 1.0.0-pre-6 to 1.0.0-pre-60
@@ -1,2 +0,2 @@ | ||
import type { DryvOptions, DryvProxy, DryvValidationRuleSet } from './typings'; | ||
export declare function annotate<TModel extends object>(model: DryvProxy<TModel>, ruleSet: DryvValidationRuleSet<TModel>, options: DryvOptions): void; | ||
import { DryvOptions, DryvProxy, DryvValidationRuleSet } from './typings'; | ||
export declare function annotate<TModel extends object, TParameters = object>(model: DryvProxy<TModel>, ruleSet: DryvValidationRuleSet<TModel, TParameters>, options: DryvOptions): void; |
import { isDryvValidatable } from './'; | ||
export function annotate(model, ruleSet, options) { | ||
annotateObject(model.$dryv, ruleSet, options); | ||
annotateDryvObject(model.$validatable.value, ruleSet, options); | ||
} | ||
function annotateObject(validatable, ruleSet, options) { | ||
function annotateDryvObject(dryvObject, ruleSet, options) { | ||
var _a; | ||
const model = validatable.value; | ||
for (const key in model) { | ||
for (const key in dryvObject) { | ||
if ((_a = options.excludedFields) === null || _a === void 0 ? void 0 : _a.find((regexp) => regexp.test(key))) { | ||
continue; | ||
} | ||
const value = model[key]; | ||
const value = dryvObject[key]; | ||
if (isDryvValidatable(value)) { | ||
annotateValidatable(value, ruleSet); | ||
} | ||
if (typeof value === 'object') { | ||
annotateObject(value, ruleSet, options); | ||
else if (typeof value === 'object') { | ||
annotateDryvObject(value, ruleSet, options); | ||
} | ||
@@ -22,6 +21,5 @@ } | ||
function annotateValidatable(validatable, ruleSet) { | ||
var _a, _b, _c; | ||
validatable.required = | ||
(_c = (_b = (_a = ruleSet.validators) === null || _a === void 0 ? void 0 : _a[validatable.field]) === null || _b === void 0 ? void 0 : _b.find((rule) => { var _a; return (_a = rule.annotations) === null || _a === void 0 ? void 0 : _a.required; })) !== null && _c !== void 0 ? _c : false; | ||
var _a, _b; | ||
validatable.required = !!((_b = (_a = ruleSet.validators) === null || _a === void 0 ? void 0 : _a[validatable.path]) === null || _b === void 0 ? void 0 : _b.find((rule) => { var _a; return (_a = rule.annotations) === null || _a === void 0 ? void 0 : _a.required; })); | ||
} | ||
//# sourceMappingURL=annotate.js.map |
@@ -20,3 +20,3 @@ import { dryvProxyHandler } from './dryvProxyHandler'; | ||
.filter((prop) => { var _a; return !((_a = options.excludedFields) === null || _a === void 0 ? void 0 : _a.find((regexp) => regexp.test(prop))); }) | ||
.forEach((prop) => (proxy[prop] = proxy[prop])); | ||
.forEach((prop) => (proxy[prop] = model[prop])); | ||
return proxy; | ||
@@ -23,0 +23,0 @@ } |
@@ -6,69 +6,81 @@ import { dryvProxy, isDryvProxy } from '.'; | ||
export function dryvProxyHandler(field, session, options) { | ||
const _excludedFields = {}; | ||
let _dryv = null; | ||
return { | ||
get(target, fieldSymbol, receiver) { | ||
const fieldName = String(fieldSymbol); | ||
if (fieldName === '$dryv') { | ||
return getDryv(receiver); | ||
return new DryvProxyHandler(field, session, options); | ||
} | ||
class DryvProxyHandler { | ||
constructor(field, session, options) { | ||
this.field = field; | ||
this.session = session; | ||
this.options = options; | ||
this._excludedFields = {}; | ||
this._validatable = null; | ||
this._values = options.objectWrapper({}); | ||
} | ||
get(target, fieldSymbol, receiver) { | ||
const fieldName = String(fieldSymbol); | ||
if (fieldName === '$validatable') { | ||
return this.getDryv(receiver); | ||
} | ||
if (this.isExcludedField(fieldName)) { | ||
return Reflect.get(target, fieldName, receiver); | ||
} | ||
if (this._values[fieldName] !== undefined) { | ||
return this._values[fieldName]; | ||
} | ||
const originalValue = Reflect.get(target, fieldName, receiver); | ||
const field = fieldName; | ||
let resultValue; | ||
if (originalValue && typeof originalValue === 'object' && !Array.isArray(originalValue)) { | ||
resultValue = this.ensureObjectProxy(originalValue, field, receiver, this.session); | ||
if (resultValue !== originalValue) { | ||
this._values[fieldName] = resultValue; | ||
} | ||
if (isExcludedField(fieldName)) { | ||
return Reflect.get(target, fieldName, receiver); | ||
} | ||
const originalValue = Reflect.get(target, fieldName, receiver); | ||
const field = fieldName; | ||
let resultValue; | ||
if (originalValue && typeof originalValue === 'object') { | ||
resultValue = ensureObjectProxy(originalValue, field, receiver, session); | ||
if (resultValue !== originalValue) { | ||
Reflect.set(target, fieldName, resultValue); | ||
} | ||
} | ||
else if (typeof originalValue !== 'function') { | ||
ensureValueProxy(field, receiver); | ||
resultValue = originalValue; | ||
} | ||
return resultValue; | ||
}, | ||
set(target, fieldSymbol, value, receiver) { | ||
const fieldName = String(fieldSymbol); | ||
if (fieldName === '$dryv') { | ||
throw new Error('The $dryv property is read-only.'); | ||
} | ||
const field = fieldName; | ||
if (typeof value === 'function') { | ||
return Reflect.set(target, field, value); | ||
} | ||
if (isExcludedField(fieldName)) { | ||
return Reflect.set(target, field, value); | ||
} | ||
const originalValue = Reflect.get(target, field, receiver); | ||
if (!value && isDryvProxy(originalValue)) { | ||
originalValue.$dryv.parent = undefined; | ||
} | ||
let targetValue; | ||
let proxy = undefined; | ||
if (value && typeof value === 'object') { | ||
targetValue = ensureObjectProxy(value, field, receiver, session); | ||
} | ||
else { | ||
proxy = ensureValueProxy(field, receiver); | ||
targetValue = value; | ||
} | ||
const result = Reflect.set(target, field, targetValue); | ||
proxy === null || proxy === void 0 ? void 0 : proxy.validate().catch(console.error); | ||
return result; | ||
} | ||
}; | ||
function ensureObjectProxy(value, field, receiver, session) { | ||
else if (typeof originalValue !== 'function') { | ||
this.ensureValueProxy(field, receiver, this.session); | ||
resultValue = originalValue; | ||
} | ||
return resultValue; | ||
} | ||
set(target, fieldSymbol, value, receiver) { | ||
var _a; | ||
const fieldName = String(fieldSymbol); | ||
if (fieldName === '$validatable') { | ||
throw new Error('The $validatable property is read-only.'); | ||
} | ||
const field = fieldName; | ||
if (typeof value === 'function') { | ||
return Reflect.set(target, field, value, receiver); | ||
} | ||
if (this.isExcludedField(fieldName)) { | ||
return Reflect.set(target, field, value, receiver); | ||
} | ||
const originalValue = (_a = this._values[fieldName]) !== null && _a !== void 0 ? _a : Reflect.get(target, field, receiver); | ||
if (!value && isDryvProxy(originalValue)) { | ||
originalValue.$validatable.parent = undefined; | ||
} | ||
let targetValue = value; | ||
let proxy = undefined; | ||
if (value && typeof value === 'object' && !Array.isArray(value)) { | ||
targetValue = this.ensureObjectProxy(value, field, receiver, this.session); | ||
} | ||
else { | ||
proxy = this.ensureValueProxy(field, receiver, this.session); | ||
targetValue = value; | ||
} | ||
this._values[fieldName] = targetValue; | ||
const result = Reflect.set(target, field, value, receiver); | ||
proxy === null || proxy === void 0 ? void 0 : proxy.validate().catch(console.error); | ||
return result; | ||
} | ||
ensureObjectProxy(value, field, receiver, session) { | ||
const proxy = !isDryvProxy(value) | ||
? dryvProxy(value, field, session, options) | ||
? dryvProxy(value, field, session, this.options) | ||
: value; | ||
const dryv = getDryv(receiver); | ||
dryv.value[field] = proxy.$dryv.value; | ||
proxy.$dryv.parent = dryv; | ||
const dryv = this.getDryv(receiver); | ||
dryv.value[field] = proxy.$validatable.value; | ||
proxy.$validatable.parent = dryv; | ||
return proxy; | ||
} | ||
function ensureValueProxy(field, receiver) { | ||
const dryv = getDryv(receiver); | ||
ensureValueProxy(field, receiver, session) { | ||
const dryv = this.getDryv(receiver); | ||
const dryvObject = dryv.value; | ||
@@ -78,21 +90,21 @@ if (isDryvValidatable(dryvObject[field])) { | ||
} | ||
const validatable = dryvValidatableValue(field, dryv, options, () => receiver[field], (value) => (receiver[field] = value)); | ||
const proxy = options.objectWrapper(validatable); | ||
const validatable = dryvValidatableValue(field, dryv, session, this.options, () => receiver[field], (value) => (receiver[field] = value)); | ||
const proxy = this.options.objectWrapper(validatable); | ||
dryvObject[field] = proxy; | ||
return proxy; | ||
} | ||
function getDryv(model) { | ||
if (!_dryv) { | ||
_dryv = dryvValidatableObject(field, session, model, options); | ||
getDryv(model) { | ||
if (!this._validatable) { | ||
this._validatable = dryvValidatableObject(this.field, this.session, model, this.options); | ||
} | ||
return _dryv; | ||
return this._validatable; | ||
} | ||
function isExcludedField(field) { | ||
isExcludedField(field) { | ||
var _a; | ||
if (_excludedFields[field] === undefined) { | ||
_excludedFields[field] = !!((_a = options.excludedFields) === null || _a === void 0 ? void 0 : _a.find((regexp) => regexp === null || regexp === void 0 ? void 0 : regexp.test(field))); | ||
if (this._excludedFields[field] === undefined) { | ||
this._excludedFields[field] = !!((_a = this.options.excludedFields) === null || _a === void 0 ? void 0 : _a.find((regexp) => regexp === null || regexp === void 0 ? void 0 : regexp.test(field))); | ||
} | ||
return _excludedFields[field]; | ||
return this._excludedFields[field]; | ||
} | ||
} | ||
//# sourceMappingURL=dryvProxyHandler.js.map |
import type { DryvValidationRuleSet } from './typings'; | ||
export declare function dryvRuleSet<TModel extends object>(ruleSetName: string): DryvValidationRuleSet<TModel> | undefined; | ||
export declare function dryvRuleSet<TModel extends object, TParameters = object>(ruleSetName: string): DryvValidationRuleSet<TModel, TParameters> | undefined; |
@@ -1,2 +0,4 @@ | ||
import type { DryvObject, DryvOptions, DryvValidatableInternal, DryvValidationSession } from './typings'; | ||
export declare function dryvValidatableObject<TModel extends object = any, TValue extends object = any>(field: keyof TModel | undefined, parentOrSession: DryvValidatableInternal | DryvValidationSession<TModel> | undefined, model: TModel, options: DryvOptions): DryvValidatableInternal<TModel, DryvObject<TValue>>; | ||
import { DryvObjectValidator, DryvEditingObject } from '../core' | ||
export declare function dryvEditingObject<TModel extends object>( | ||
validator: DryvObjectValidator<TModel> | ||
): DryvEditingObject<TModel> |
@@ -1,89 +0,39 @@ | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
import { isDryvValidatable } from './isDryvValidatable'; | ||
import { dryvValidatableValue } from './dryvValidatableValue'; | ||
export function dryvValidatableObject(field, parentOrSession, model, options) { | ||
let _parent = isDryvValidatable(parentOrSession) | ||
? parentOrSession | ||
: undefined; | ||
const _session = _parent | ||
? undefined | ||
: parentOrSession; | ||
const _value = new Proxy({ | ||
$model: model, | ||
toJSON() { | ||
return Object.assign(Object.assign({}, this), { $model: undefined }); | ||
import { DryvFieldValidator, DryvObjectValidator } from '../core'; | ||
export function dryvValidatableObject(validator) { | ||
return new Proxy(validator, new DryvTransparentProxyHandler()); | ||
} | ||
class DryvTransparentProxyHandler { | ||
ownKeys(target) { | ||
return target.proxy ? Reflect.ownKeys(target.proxy) : []; | ||
} | ||
get(target, prop, receiver) { | ||
const innerValue = Reflect.get(target.fields, prop, receiver); | ||
return innerValue instanceof DryvObjectValidator ? innerValue.transparentProxy : innerValue; | ||
} | ||
set(target, prop, value, receiver) { | ||
const validator = target.fields[prop]; | ||
if (!(validator instanceof DryvFieldValidator)) { | ||
return Reflect.set(target.fields, prop, value, receiver); | ||
} | ||
}, { | ||
set(target, field, value, receiver) { | ||
return target.hasOwnProperty(field) || isDryvValidatable(value) | ||
? Reflect.set(target, field, value) | ||
: Reflect.set(target, field, dryvValidatableValue(field, receiver, options, () => model[field], (value) => (model[field] = value))); | ||
} | ||
}); | ||
const validatable = options.objectWrapper({ | ||
_isDryvValidatable: true, | ||
field, | ||
text: null, | ||
group: null, | ||
status: null, | ||
required: null, | ||
get value() { | ||
return _value; | ||
}, | ||
get parent() { | ||
return _parent; | ||
}, | ||
set parent(value) { | ||
_parent = value; | ||
}, | ||
get session() { | ||
var _a; | ||
return (_a = _parent === null || _parent === void 0 ? void 0 : _parent.session) !== null && _a !== void 0 ? _a : _session; | ||
}, | ||
get hasError() { | ||
return this.status === 'error'; | ||
}, | ||
get hasWarning() { | ||
return this.status === 'warning'; | ||
}, | ||
get path() { | ||
return ((_parent === null || _parent === void 0 ? void 0 : _parent.path) ? _parent.path + '.' : '') + (field ? String(field) : ''); | ||
}, | ||
validate() { | ||
var _a; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const session = (_a = _parent === null || _parent === void 0 ? void 0 : _parent.session) !== null && _a !== void 0 ? _a : _session; | ||
if (!session) { | ||
throw new Error('No validation session found'); | ||
} | ||
return session.validateObject(this); | ||
}); | ||
}, | ||
clear() { | ||
validatable.status = null; | ||
validatable.text = null; | ||
validatable.group = null; | ||
Object.values(_value) | ||
.filter((v) => isDryvValidatable(v)) | ||
.forEach((v) => v.clear()); | ||
}, | ||
set(response) { | ||
Object.values(_value) | ||
.filter((v) => isDryvValidatable(v)) | ||
.forEach((v) => v.set(response)); | ||
}, | ||
toJSON() { | ||
return Object.assign(Object.assign({}, this), { parent: undefined, _isDryvValidatable: undefined }); | ||
} | ||
}); | ||
return validatable; | ||
validator.value = value; | ||
return true; | ||
} | ||
has(target, key) { | ||
return !!target.fields[key]; | ||
} | ||
getOwnPropertyDescriptor(target, key) { | ||
if (!target.fields) | ||
return undefined; | ||
const value = target.fields[key]; | ||
const decriptor = Reflect.getOwnPropertyDescriptor(target.fields, key); | ||
return value | ||
? { | ||
value: value instanceof DryvObjectValidator ? value.transparentProxy : value, | ||
writable: value instanceof DryvObjectValidator ? false : decriptor === null || decriptor === void 0 ? void 0 : decriptor.writable, | ||
enumerable: decriptor === null || decriptor === void 0 ? void 0 : decriptor.enumerable, | ||
configurable: decriptor === null || decriptor === void 0 ? void 0 : decriptor.configurable | ||
} | ||
: undefined; | ||
} | ||
} | ||
//# sourceMappingURL=dryvValidatableObject.js.map |
@@ -1,2 +0,9 @@ | ||
import type { DryvOptions, DryvValidatableInternal } from './typings'; | ||
export declare function dryvValidatableValue<TModel extends object = any, TValue = any>(field: keyof TModel | undefined, parent: DryvValidatableInternal | undefined, options: DryvOptions, getter: () => TValue, setter: (value: TValue) => void): DryvValidatableInternal<TModel, TValue>; | ||
import type { DryvValidationSession, DryvOptions, DryvValidationInternal } from './typings' | ||
export declare function dryvValidationValue<TModel extends object = any, TValue = any>( | ||
field: keyof TModel | undefined, | ||
parent: DryvValidationInternal | undefined, | ||
session: DryvValidationSession<TModel> | undefined, | ||
options: DryvOptions, | ||
getter: () => TValue, | ||
setter: (value: TValue) => void | ||
): DryvValidationInternal<TModel, TValue> |
@@ -10,9 +10,15 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
}; | ||
export function dryvValidatableValue(field, parent, options, getter, setter) { | ||
export function dryvValidatableValue(field, parent, session, options, getter, setter) { | ||
let _text = null; | ||
const validatable = options.objectWrapper({ | ||
_isDryvValidatable: true, | ||
field, | ||
text: null, | ||
get text() { | ||
return _text; | ||
}, | ||
set text(value) { | ||
_text = value; | ||
}, | ||
group: null, | ||
status: null, | ||
type: null, | ||
get value() { | ||
@@ -34,14 +40,18 @@ return getter(); | ||
get hasError() { | ||
return this.status === 'error'; | ||
return this.type === 'error'; | ||
}, | ||
get hasWarning() { | ||
return this.status === 'warning'; | ||
return this.type === 'warning'; | ||
}, | ||
get isSuccess() { | ||
return !this.hasError && !this.hasWarning; | ||
}, | ||
validate() { | ||
var _a; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const session = parent === null || parent === void 0 ? void 0 : parent.session; | ||
if (!session) { | ||
const _session = (_a = parent === null || parent === void 0 ? void 0 : parent.session) !== null && _a !== void 0 ? _a : session; | ||
if (!_session) { | ||
throw new Error('No validation session found'); | ||
} | ||
return session.validateField(this); | ||
return _session.validateField(validatable); | ||
}); | ||
@@ -53,3 +63,12 @@ }, | ||
clear() { | ||
validatable.status = null; | ||
var _a; | ||
const _session = (_a = parent === null || parent === void 0 ? void 0 : parent.session) !== null && _a !== void 0 ? _a : session; | ||
if (!_session) { | ||
throw new Error('No validation session found'); | ||
} | ||
_session.results.fields[this.path] = undefined; | ||
if (validatable.group) { | ||
_session.results.groups[validatable.group] = undefined; | ||
} | ||
validatable.type = null; | ||
validatable.text = null; | ||
@@ -61,6 +80,6 @@ validatable.group = null; | ||
const message = messages === null || messages === void 0 ? void 0 : messages[this.path]; | ||
if (message && message.status !== 'success') { | ||
if (message && message.type !== 'success') { | ||
validatable.text = message.text; | ||
validatable.group = message.group; | ||
validatable.status = message.status; | ||
validatable.type = message.type; | ||
} | ||
@@ -70,7 +89,11 @@ else { | ||
validatable.group = undefined; | ||
validatable.status = undefined; | ||
validatable.type = undefined; | ||
} | ||
return validatable.isSuccess; | ||
}, | ||
updateValue(value) { | ||
this.value = value; | ||
}, | ||
toJSON() { | ||
return Object.assign(Object.assign({}, this), { parent: undefined, _isDryvValidatable: undefined }); | ||
return Object.assign(Object.assign({}, this), { parent: undefined, _isDryvValidatable: undefined, session: undefined }); | ||
} | ||
@@ -77,0 +100,0 @@ }); |
@@ -1,2 +0,37 @@ | ||
import type { DryvOptions, DryvValidationRuleSet, DryvValidationSession } from './typings'; | ||
export declare function dryvValidationSession<TModel extends object>(options: DryvOptions, ruleSet: DryvValidationRuleSet<TModel>): DryvValidationSession<TModel>; | ||
import { DryvFieldValidationResult, DryvOptions, DryvValidationResult, DryvValidationRule, DryvValidationRuleSet, DryvValidationSession } from '../core/typings'; | ||
import { DryvObjectValidator } from '../core/DryvObjectValidator'; | ||
import { DryvFieldValidator } from '../core/DryvFieldValidator'; | ||
export declare class DryvValidationSessionImplementation<TModel extends object, TParameters = any> implements DryvValidationSession<TModel, TParameters> { | ||
private options; | ||
private ruleSet; | ||
private _depth; | ||
private _excludedFields; | ||
private _isTriggered; | ||
private _processedFields; | ||
readonly results: { | ||
fields: Record<string, DryvFieldValidationResult | undefined>; | ||
groups: Record<string, DryvFieldValidationResult | undefined>; | ||
}; | ||
readonly dryv: { | ||
callServer(url: string, method: string, data: any): Promise<any>; | ||
handleResult(session: DryvValidationSession<TModel>, $m: TModel, field: keyof TModel | string, rule: DryvValidationRule<TModel> | undefined | null, result: any): Promise<any>; | ||
valueOfDate(date: string, locale: string, format: string): number; | ||
}; | ||
constructor(options: DryvOptions, ruleSet: DryvValidationRuleSet<TModel, TParameters>); | ||
get isValidating(): boolean; | ||
validateObject(objectValidator: DryvObjectValidator<TModel>): Promise<DryvValidationResult>; | ||
validateField(field: DryvFieldValidator<TModel>, model?: TModel): Promise<DryvValidationResult>; | ||
private canValidateFields; | ||
private startValidationChain; | ||
private endValidationChain; | ||
private traverseFields; | ||
private isExcludedField; | ||
private validateFieldInternal; | ||
private runDisablers; | ||
private runValidators; | ||
private getModel; | ||
private success; | ||
private createObjectResults; | ||
private createFieldValidationResult; | ||
private hashCode; | ||
} |
@@ -10,154 +10,174 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
}; | ||
import { isDryvProxy, isDryvValidatable } from '.'; | ||
import { getMemberByPath } from './getMemberByPath'; | ||
export function dryvValidationSession(options, ruleSet) { | ||
if (!options.callServer) { | ||
throw new Error('The callServer option is required.'); | ||
} | ||
if (!options.handleResult) { | ||
throw new Error('The handleResult option is required.'); | ||
} | ||
if (!options.valueOfDate) { | ||
throw new Error('The valueOfDate option is required.'); | ||
} | ||
const _excludedFields = {}; | ||
let _isTriggered = false; | ||
let _depth = 0; | ||
let _processedFields = undefined; | ||
function isValidating() { | ||
return _depth > 0; | ||
} | ||
const session = { | ||
dryv: { | ||
import { DryvValidator } from '../core/DryvValidator'; | ||
import { getValidatorByPath } from '../core/getMemberByPath'; | ||
export class DryvValidationSessionImplementation { | ||
constructor(options, ruleSet) { | ||
this.options = options; | ||
this.ruleSet = ruleSet; | ||
this._depth = 0; | ||
this._excludedFields = {}; | ||
this._isTriggered = false; | ||
this._processedFields = undefined; | ||
this.dryv = { | ||
callServer: options.callServer, | ||
handleResult: options.handleResult, | ||
valueOfDate: options.valueOfDate | ||
}, | ||
validateObject(objOrProxy) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const obj = isDryvProxy(objOrProxy) | ||
? objOrProxy.$dryv | ||
: objOrProxy; | ||
if (!obj) { | ||
throw new Error('The value null of undefined is not validatable.'); | ||
} | ||
_depth++; | ||
_isTriggered = true; | ||
try { | ||
const results = (yield Promise.all(Object.entries(obj.value) | ||
.filter(([key, value]) => isDryvValidatable(value) && !isExcludedField(key)) | ||
.map(([_, value]) => value.validate()))).filter((result) => !!result); | ||
const fieldResults = results.filter((r) => r).flatMap((r) => r.results); | ||
const warnings = fieldResults.filter((r) => r.status === 'warning'); | ||
const hasErrors = fieldResults.some((r) => r.status === 'error'); | ||
obj.status = hasErrors ? 'error' : warnings.length > 0 ? 'warning' : 'success'; | ||
return { | ||
results: fieldResults, | ||
hasErrors: hasErrors, | ||
hasWarnings: warnings.length > 0, | ||
warningHash: fieldResults.map((r) => r.text).join('|'), | ||
success: !hasErrors && warnings.length === 0 | ||
}; | ||
} | ||
finally { | ||
_depth--; | ||
} | ||
}); | ||
}, | ||
validateField(field, model) { | ||
var _a; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
switch (options.validationTrigger) { | ||
case 'auto': | ||
if (session.$initializing) { | ||
return success(); | ||
} | ||
break; | ||
case 'manual': | ||
if (!isValidating()) { | ||
return success(); | ||
} | ||
break; | ||
case 'autoAfterManual': | ||
if (!_isTriggered && !isValidating()) { | ||
return success(); | ||
} | ||
break; | ||
} | ||
if (_processedFields === null || _processedFields === void 0 ? void 0 : _processedFields[field.field]) { | ||
return success(); | ||
} | ||
if (!model) { | ||
model = getModel(field); | ||
} | ||
const newValidationChain = !_processedFields; | ||
}; | ||
this.results = options.objectWrapper({ | ||
fields: {}, | ||
groups: {} | ||
}); | ||
} | ||
get isValidating() { | ||
return this._depth > 0; | ||
} | ||
validateObject(objectValidator) { | ||
var _a; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (yield this.runDisablers(objectValidator.rootModel, (_a = objectValidator.field) !== null && _a !== void 0 ? _a : '')) { | ||
objectValidator.clear(); | ||
return { | ||
success: true, | ||
path: objectValidator.path, | ||
hasErrors: false, | ||
hasWarnings: false, | ||
warningHash: null, | ||
results: [] | ||
}; | ||
} | ||
this._depth++; | ||
this._isTriggered = true; | ||
try { | ||
const newValidationChain = this.startValidationChain(); | ||
const fieldResults = yield Promise.all(Array.from(this.traverseFields(objectValidator.value)).map(([, value]) => value.validate().then((result) => { var _a; return (Object.assign(Object.assign({}, result), { path: (_a = value.path) !== null && _a !== void 0 ? _a : undefined })); }))); | ||
const result = this.createObjectResults(fieldResults.filter((r) => !!r)); | ||
objectValidator.type = result.hasErrors ? 'error' : result.hasWarnings ? 'warning' : 'success'; | ||
if (newValidationChain) { | ||
_processedFields = {}; | ||
this.endValidationChain(); | ||
} | ||
const result = yield validateFieldInternal(session, ruleSet, model, field, options); | ||
if (newValidationChain) { | ||
_processedFields = undefined; | ||
return result; | ||
} | ||
finally { | ||
this._depth--; | ||
} | ||
}); | ||
} | ||
validateField(field, model) { | ||
var _a; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (!this.canValidateFields() || ((_a = this._processedFields) === null || _a === void 0 ? void 0 : _a[field.field])) { | ||
return this.success(field.path); | ||
} | ||
if (!model) { | ||
model = this.getModel(field); | ||
} | ||
const newValidationChain = this.startValidationChain(); | ||
const fieldResult = yield this.validateFieldInternal(model, field); | ||
const result = this.createFieldValidationResult(fieldResult, field); | ||
this.results.fields[field.path] = result.success ? undefined : fieldResult !== null && fieldResult !== void 0 ? fieldResult : undefined; | ||
if (fieldResult === null || fieldResult === void 0 ? void 0 : fieldResult.group) { | ||
this.results.groups[fieldResult === null || fieldResult === void 0 ? void 0 : fieldResult.group] = result.success ? undefined : fieldResult; | ||
} | ||
if (newValidationChain) { | ||
this.endValidationChain(); | ||
} | ||
return result; | ||
}); | ||
} | ||
canValidateFields() { | ||
switch (this.options.validationTrigger) { | ||
case 'auto': | ||
break; | ||
case 'manual': | ||
if (!this.isValidating) { | ||
return false; | ||
} | ||
if (result) { | ||
field.status = result.status; | ||
field.text = result.text; | ||
field.group = result.group; | ||
const status = (_a = result.status) === null || _a === void 0 ? void 0 : _a.toLowerCase(); | ||
return status === 'success' | ||
? success() | ||
: { | ||
results: [result], | ||
hasErrors: status === 'error', | ||
hasWarnings: status === 'warning', | ||
warningHash: status === 'warning' ? result.text : null, | ||
success: status === 'success' || !status | ||
}; | ||
break; | ||
case 'autoAfterManual': | ||
if (!this._isTriggered && !this.isValidating) { | ||
return false; | ||
} | ||
else { | ||
field.status = 'success'; | ||
field.text = null; | ||
field.group = null; | ||
return success(); | ||
} | ||
}); | ||
break; | ||
} | ||
}; | ||
return session; | ||
function isExcludedField(fieldName, path) { | ||
if (!options.excludedFields) { | ||
return true; | ||
} | ||
startValidationChain() { | ||
const newValidationChain = !this._processedFields; | ||
if (newValidationChain) { | ||
this._processedFields = {}; | ||
} | ||
return newValidationChain; | ||
} | ||
endValidationChain() { | ||
this._processedFields = undefined; | ||
} | ||
*traverseFields(obj, parentPath) { | ||
var _a, _b; | ||
if (!parentPath) { | ||
parentPath = ''; | ||
} | ||
for (const key in obj) { | ||
if (!(!this.isExcludedField(key) && obj.hasOwnProperty(key))) { | ||
console.log('*** excluded field ' + key); | ||
continue; | ||
} | ||
const path = parentPath ? parentPath + '.' + key : key; | ||
const value = obj[key]; | ||
if (typeof value !== 'object') { | ||
console.log('*** what field ' + path); | ||
continue; | ||
} | ||
const model = (_a = obj.$model) !== null && _a !== void 0 ? _a : obj; | ||
const disablers = (_b = this.ruleSet.disablers) === null || _b === void 0 ? void 0 : _b[key]; | ||
if (disablers && disablers.find((disabler) => disabler.validate(model, this))) { | ||
console.log('*** skipping field ' + path); | ||
continue; | ||
} | ||
if (value instanceof DryvValidator) { | ||
console.log('*** using field ' + path); | ||
yield [path, value]; | ||
} | ||
else { | ||
console.log('*** drilling into field ' + path); | ||
yield* this.traverseFields(value, path); | ||
} | ||
} | ||
} | ||
isExcludedField(fieldName, path) { | ||
if (!this.options.excludedFields) { | ||
return false; | ||
} | ||
const key = path ? path + '.' + fieldName : fieldName; | ||
if (_excludedFields[key] === undefined) { | ||
_excludedFields[key] = !!options.excludedFields.find((regexp) => regexp.test(key)); | ||
if (this._excludedFields[key] === undefined) { | ||
this._excludedFields[key] = !!this.options.excludedFields.find((regexp) => regexp.test(key)); | ||
} | ||
return _excludedFields[key]; | ||
return this._excludedFields[key]; | ||
} | ||
function validateFieldInternal(session, ruleSet, model, validatable, options) { | ||
var _a; | ||
validateFieldInternal(model, validatable) { | ||
var _a, _b; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const field = validatable.field; | ||
if (!field || !ruleSet) { | ||
if (!field || !this.ruleSet) { | ||
return Promise.resolve(null); | ||
} | ||
if (_processedFields) { | ||
_processedFields[field] = true; | ||
if (this._processedFields) { | ||
this._processedFields[field] = true; | ||
} | ||
const rules = (_a = ruleSet === null || ruleSet === void 0 ? void 0 : ruleSet.validators) === null || _a === void 0 ? void 0 : _a[field]; | ||
const rules = (_b = (_a = this.ruleSet) === null || _a === void 0 ? void 0 : _a.validators) === null || _b === void 0 ? void 0 : _b[validatable.path]; | ||
if (!rules || rules.length <= 0) { | ||
return Promise.resolve(null); | ||
} | ||
if (yield runDisablers(session, ruleSet, model, field)) { | ||
if (yield this.runDisablers(model, field)) { | ||
return Promise.resolve(null); | ||
} | ||
return yield runValidators(session, rules, model, validatable, options); | ||
return yield this.runValidators(rules, model, validatable); | ||
}); | ||
} | ||
function runDisablers(session, ruleSet, model, field) { | ||
var _a; | ||
runDisablers(model, field) { | ||
var _a, _b; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const disablers = (_a = ruleSet === null || ruleSet === void 0 ? void 0 : ruleSet.disablers) === null || _a === void 0 ? void 0 : _a[field]; | ||
const disablers = (_b = (_a = this.ruleSet) === null || _a === void 0 ? void 0 : _a.disablers) === null || _b === void 0 ? void 0 : _b[field]; | ||
if (disablers && disablers.length > 0) { | ||
for (const rule of disablers) { | ||
if (yield rule.validate(model, session)) { | ||
if (yield rule.validate(model, this)) { | ||
return true; | ||
@@ -170,3 +190,3 @@ } | ||
} | ||
function runValidators(session, rules, model, validatable, options) { | ||
runValidators(rules, model, validatable) { | ||
var _a; | ||
@@ -178,7 +198,13 @@ return __awaiter(this, void 0, void 0, function* () { | ||
(_a = rule.related) === null || _a === void 0 ? void 0 : _a.forEach((relatedField) => { | ||
const field = getMemberByPath(model.$dryv.value, relatedField); | ||
session.validateField(field, model); | ||
if (!relatedField || relatedField === validatable.path) { | ||
return; | ||
} | ||
const field = getValidatorByPath(validatable.rootValidator, relatedField); | ||
if (!field) { | ||
return; | ||
} | ||
this.validateField(field, model); | ||
}); | ||
const r = yield rule.validate(model, session); | ||
if (!r) { | ||
const r = yield rule.validate(model, this); | ||
if (!r || r === true) { | ||
} | ||
@@ -188,10 +214,13 @@ else if (typeof r === 'string') { | ||
path: validatable.path, | ||
status: 'error', | ||
type: 'error', | ||
text: r, | ||
group: null | ||
group: rule.group | ||
}; | ||
break; | ||
} | ||
else if (r.status !== 'success') { | ||
else if (r.type !== 'success') { | ||
result = r; | ||
if (!result.group) { | ||
result.group = rule.group; | ||
} | ||
break; | ||
@@ -203,6 +232,6 @@ } | ||
console.error(`DRYV: Error validating field '${String(validatable.field)}'`, error); | ||
if (options.exceptionHandling === 'failValidation') { | ||
if (this.options.exceptionHandling === 'failValidation') { | ||
result = { | ||
path: validatable.path, | ||
status: 'error', | ||
type: 'error', | ||
text: 'Validation failed.', | ||
@@ -213,21 +242,76 @@ group: null | ||
} | ||
return result && result.status !== 'success' ? result : null; | ||
return result && result.type !== 'success' ? result : null; | ||
}); | ||
} | ||
} | ||
function getModel(parent) { | ||
while (parent.parent) { | ||
parent = parent.parent; | ||
getModel(parent) { | ||
while (parent.parent) { | ||
parent = parent.parent; | ||
} | ||
return parent.model; | ||
} | ||
return parent.value.$model; | ||
success(path) { | ||
return { | ||
results: [], | ||
success: true, | ||
hasErrors: false, | ||
hasWarnings: false, | ||
warningHash: null, | ||
path | ||
}; | ||
} | ||
createObjectResults(results) { | ||
const fieldResults = results | ||
.filter((r) => r) | ||
.flatMap((r) => r.results.map((r2) => (Object.assign(Object.assign({}, r2), { path: r.path })))); | ||
const hasWarnings = fieldResults.some((r) => r.type === 'warning'); | ||
const hasErrors = fieldResults.some((r) => r.type === 'error'); | ||
return { | ||
results: fieldResults, | ||
hasErrors: hasErrors, | ||
hasWarnings: hasWarnings, | ||
warningHash: this.hashCode(fieldResults | ||
.filter((r) => r.type === 'warning') | ||
.map((r) => r.text) | ||
.join()), | ||
success: !hasErrors && !hasWarnings | ||
}; | ||
} | ||
createFieldValidationResult(result, field) { | ||
var _a, _b, _c, _d; | ||
if (result) { | ||
field.type = (_a = result.type) !== null && _a !== void 0 ? _a : 'success'; | ||
field.text = (_b = result.text) !== null && _b !== void 0 ? _b : null; | ||
field.group = (_c = result.group) !== null && _c !== void 0 ? _c : null; | ||
const type = (_d = result.type) === null || _d === void 0 ? void 0 : _d.toLowerCase(); | ||
return type === 'success' | ||
? this.success(field.path) | ||
: { | ||
results: [result], | ||
hasErrors: type === 'error', | ||
hasWarnings: type === 'warning', | ||
warningHash: type === 'warning' ? result.text : null, | ||
success: type === 'success' || !type, | ||
path: String(field.path) | ||
}; | ||
} | ||
else { | ||
field.type = 'success'; | ||
field.text = null; | ||
field.group = null; | ||
return this.success(field.path); | ||
} | ||
} | ||
hashCode(text) { | ||
if (!text || text.length === 0) { | ||
return ''; | ||
} | ||
let hash = 0; | ||
for (let i = 0; i < text.length; i++) { | ||
const chr = text.charCodeAt(i); | ||
hash = (hash << 5) - hash + chr; | ||
hash |= 0; | ||
} | ||
return Math.abs(hash).toString(16); | ||
} | ||
} | ||
function success() { | ||
return { | ||
results: [], | ||
success: true, | ||
hasErrors: false, | ||
hasWarnings: false, | ||
warningHash: null | ||
}; | ||
} | ||
//# sourceMappingURL=dryvValidationSession.js.map |
@@ -1,1 +0,1 @@ | ||
export declare function getMemberByPath<TResult = any>(obj: any, path: string | symbol): TResult; | ||
export declare function getMemberByPath<TModel extends object, TResult = any>(obj: TModel, path: string): TResult | TModel | null; |
@@ -6,7 +6,7 @@ export function getMemberByPath(obj, path) { | ||
let result = obj; | ||
for (const part of String(path).split('.')) { | ||
if (result == null) { | ||
return result; | ||
for (const part of path.split('.')) { | ||
result = result[part]; | ||
if (result === null) { | ||
return null; | ||
} | ||
result = result[part]; | ||
} | ||
@@ -13,0 +13,0 @@ return result; |
@@ -1,9 +0,8 @@ | ||
export * from './dryvProxy'; | ||
export * from './dryvValidationSession'; | ||
export * from './isDryvValidatable'; | ||
export * from './isDryvProxy'; | ||
export * from './DryvValidationSessionImplementation'; | ||
export * from './dryvOptions'; | ||
export * from './dryvRuleSet'; | ||
export * from './annotate'; | ||
export * from './defaultDryvOptions'; | ||
export * from './typings'; | ||
export * from './DryvFieldValidator'; | ||
export * from './DryvObjectValidator'; | ||
export * from './DryvValidator'; |
@@ -1,10 +0,9 @@ | ||
export * from './dryvProxy'; | ||
export * from './dryvValidationSession'; | ||
export * from './isDryvValidatable'; | ||
export * from './isDryvProxy'; | ||
export * from './DryvValidationSessionImplementation'; | ||
export * from './dryvOptions'; | ||
export * from './dryvRuleSet'; | ||
export * from './annotate'; | ||
export * from './defaultDryvOptions'; | ||
export * from './typings'; | ||
export * from './DryvFieldValidator'; | ||
export * from './DryvObjectValidator'; | ||
export * from './DryvValidator'; | ||
//# sourceMappingURL=index.js.map |
export function isDryvProxy(model) { | ||
return !!(model === null || model === void 0 ? void 0 : model.$dryv); | ||
return !!(model === null || model === void 0 ? void 0 : model.$validatable); | ||
} | ||
//# sourceMappingURL=isDryvProxy.js.map |
@@ -1,2 +0,4 @@ | ||
import type { DryvValidatable } from './typings'; | ||
export declare function isDryvValidatable<TModel extends object, TValue>(model: TValue | DryvValidatable<TModel, TValue>): model is DryvValidatable<TModel, TValue>; | ||
import type { DryvEditingField } from './typings' | ||
export declare function isDryvValidation<TModel extends object, TValue>( | ||
model: TValue | DryvEditingField<TModel, TValue> | ||
): model is DryvEditingField<TModel, TValue> |
@@ -1,2 +0,2 @@ | ||
import type { DryvValidatable } from './typings'; | ||
export declare function isDryvValidatable<TModel extends object, TValue>(model: TValue | DryvValidatable<TModel, TValue>): model is DryvValidatable<TModel, TValue>; | ||
import type { DryvEditingField } from '../core/typings' | ||
export declare function isDryvValidationValue(model: any): model is DryvEditingField |
@@ -1,4 +0,4 @@ | ||
export function isDryvValidatable(model) { | ||
return model === null || model === void 0 ? void 0 : model._isDryvValidatable; | ||
export function isDryvValidatableValue(model) { | ||
return !!(model === null || model === void 0 ? void 0 : model._isDryvValidatableValue); | ||
} | ||
//# sourceMappingURL=isDryvValidatableValue.js.map |
@@ -1,103 +0,126 @@ | ||
export type DryvValidateFunctionResult = DryvFieldValidationResult | string | null | undefined | Promise<DryvFieldValidationResult | string | null | undefined>; | ||
import { DryvValidator } from '../core/DryvValidator' | ||
export type DryvValidateFunctionResult = | ||
| DryvFieldValidationResult | ||
| string | ||
| boolean | ||
| null | ||
| undefined | ||
| Promise<DryvFieldValidationResult | string | null | undefined> | ||
export interface DryvValidationRule<TModel extends object> { | ||
async?: boolean; | ||
annotations?: { | ||
required?: boolean; | ||
[path: string | symbol]: unknown; | ||
}; | ||
related?: (string | symbol)[]; | ||
validate: ($m: TModel, session: DryvValidationSession<TModel>) => DryvValidateFunctionResult; | ||
async?: boolean | ||
annotations?: { | ||
required?: boolean | ||
[path: string]: unknown | ||
} | ||
related?: string[] | ||
group?: string | ||
validate: ($m: TModel, session: DryvValidationSession<TModel>) => DryvValidateFunctionResult | ||
} | ||
export type DrvvRuleInvocations<TModel extends object> = { | ||
[Property in keyof TModel]?: DryvValidationRule<TModel>[]; | ||
}; | ||
[Property in keyof TModel]?: DryvValidationRule<TModel>[] | ||
} & { | ||
[path: string]: DryvValidationRule<TModel>[] | ||
} | ||
export interface DryvValidationRuleSet<TModel extends object, TParameters = object> { | ||
validators: DrvvRuleInvocations<TModel>; | ||
disablers?: DrvvRuleInvocations<TModel>; | ||
parameters?: TParameters; | ||
validators: DrvvRuleInvocations<TModel> | ||
disablers?: DrvvRuleInvocations<TModel> | ||
parameters?: TParameters | ||
} | ||
export interface DryvValidationRuleSetResolver { | ||
name: string; | ||
resolve<TModel extends object, TParameters = object>(ruleSetName: string): DryvValidationRuleSet<TModel, TParameters>; | ||
name: string | ||
resolve<TModel extends object, TParameters = object>( | ||
ruleSetName: string | ||
): DryvValidationRuleSet<TModel, TParameters> | ||
} | ||
export interface DryvValidationResult<TModel extends object> { | ||
results: DryvFieldValidationResult[]; | ||
success: boolean; | ||
hasErrors: boolean; | ||
hasWarnings: boolean; | ||
warningHash: string | undefined | null; | ||
export interface DryvValidationResult { | ||
results: DryvFieldValidationResult[] | ||
success: boolean | ||
hasErrors: boolean | ||
hasWarnings: boolean | ||
warningHash: string | undefined | null | ||
path?: string | ||
} | ||
export interface DryvFieldValidationResult { | ||
path?: string; | ||
status?: DryvValidationResultStatus; | ||
text?: string | null; | ||
group?: string | null; | ||
path?: string | ||
type?: DryvValidationResultType | ||
text?: string | null | ||
group?: string | null | ||
} | ||
export type DryvValidationResultStatus = 'error' | 'warning' | 'success' | string; | ||
export type DryvProxy<TModel extends object> = TModel & { | ||
$dryv: DryvValidatable<TModel, DryvObject<TModel>>; | ||
}; | ||
export type DryvValidationResultType = 'error' | 'warning' | 'success' | string | ||
export interface DryvGroupValidationResult { | ||
name: string; | ||
results: { | ||
status: DryvValidationResultStatus; | ||
texts: string[]; | ||
}[]; | ||
name: string | ||
results: { | ||
type: DryvValidationResultType | ||
texts: string[] | ||
}[] | ||
} | ||
export interface DryvValidatable<TModel extends object = any, TValue = any> { | ||
_isDryvValidatable: true; | ||
required?: boolean | null; | ||
text?: string | null; | ||
path?: string | null; | ||
group?: string | null; | ||
groupShown?: boolean | null; | ||
status?: DryvValidationResultStatus | null; | ||
value: TValue | undefined; | ||
parent: DryvValidatable | undefined; | ||
field: keyof TModel | undefined; | ||
get hasError(): boolean; | ||
get hasWarning(): boolean; | ||
validate(): Promise<DryvValidationResult<TModel>>; | ||
clear(): void; | ||
set(response: DryvServerValidationResponse | DryvServerErrors): void; | ||
export interface DryvValidationSessionInternal<TModel extends object, TParameters = object> | ||
extends DryvValidationSession<TModel, TParameters> { | ||
$initializing?: boolean | ||
} | ||
export interface DryvValidationGroup<TModel extends object> { | ||
name: string; | ||
fields: DryvValidatable<TModel>; | ||
text?: string | null; | ||
status?: DryvValidationResultStatus | null; | ||
export interface DryvValidationSession<TModel extends object, TParameters = any> { | ||
results: { | ||
fields: Record<string, DryvFieldValidationResult | undefined> | ||
groups: Record<string, DryvFieldValidationResult | undefined> | ||
} | ||
validateObject(objectValidator: DryvValidator<TModel>): Promise<DryvValidationResult> | ||
validateField(field: DryvValidator<TModel>, model?: TModel): Promise<DryvValidationResult> | ||
dryv: { | ||
callServer(url: string, method: string, data: any): Promise<any> | ||
handleResult( | ||
session: DryvValidationSession<TModel>, | ||
$m: TModel, | ||
field: keyof TModel | string, | ||
rule: DryvValidationRule<TModel> | undefined | null, | ||
result: any | ||
): Promise<any> | ||
valueOfDate(date: string, locale: string, format: string): number | ||
} | ||
} | ||
export type DryvObject<TModel extends object> = { | ||
[Property in keyof TModel]: TModel[Property] extends boolean ? DryvValidatable<TModel, TModel[Property]> : TModel[Property] extends string ? DryvValidatable<TModel, TModel[Property]> : TModel[Property] extends Date ? DryvValidatable<TModel, TModel[Property]> : TModel[Property] extends Array<infer ArrayType> ? DryvValidatable<TModel, TModel[Property]> : TModel[Property] extends object ? DryvObject<TModel[Property]> : TModel[Property] extends object ? DryvObject<TModel[Property]> : DryvValidatable<TModel, TModel[Property]>; | ||
} & { | ||
$model: DryvProxy<TModel> | undefined; | ||
toJSON(): any; | ||
}; | ||
export interface DryvValidationSessionInternal<TModel extends object> extends DryvValidationSession<TModel> { | ||
$initializing?: boolean; | ||
} | ||
export interface DryvValidationSession<TModel extends object> { | ||
dryv: { | ||
callServer(url: string, method: string, data: any): Promise<any>; | ||
handleResult(session: DryvValidationSession<TModel>, $m: TModel, field: keyof TModel, rule: DryvValidationRule<TModel> | undefined | null, result: any): Promise<any>; | ||
valueOfDate(date: string, locale: string, format: string): number; | ||
}; | ||
validateObject(objOrProxy: DryvValidatable<TModel> | DryvProxy<TModel>): Promise<DryvValidationResult<TModel>>; | ||
validateField<TValue>(field: DryvValidatable<TModel, TValue>, model?: DryvProxy<TModel>): Promise<DryvValidationResult<TModel>>; | ||
} | ||
export interface DryvOptions { | ||
exceptionHandling?: 'failValidation' | 'succeedValidation'; | ||
excludedFields?: RegExp[]; | ||
objectWrapper?<TObject>(object: TObject): TObject; | ||
callServer?(url: string, method: string, data: any): Promise<DryvServerValidationResponse>; | ||
handleResult?<TModel extends object>(session: DryvValidationSession<TModel>, $m: TModel, field: keyof TModel, rule: DryvValidationRule<TModel>, result: any): Promise<any>; | ||
valueOfDate?(date: string, locale: string, format: string): number; | ||
validationTrigger?: 'immediate' | 'auto' | 'manual' | 'autoAfterManual'; | ||
exceptionHandling?: 'failValidation' | 'succeedValidation' | ||
excludedFields?: RegExp[] | ||
reactiveWrapper<TObject>(object: TObject): TObject | ||
callServer?(url: string, method: string, data: any): Promise<DryvServerValidationResponse> | ||
handleResult?<TModel extends object>( | ||
session: DryvValidationSession<TModel>, | ||
$m: TModel, | ||
field: keyof TModel, | ||
rule: DryvValidationRule<TModel>, | ||
result: any | ||
): Promise<any> | ||
valueOfDate?(date: string, locale: string, format: string): number | ||
validationTrigger?: 'immediate' | 'auto' | 'manual' | 'autoAfterManual' | ||
} | ||
export type DryvServerValidationResponse = any | { | ||
success: boolean; | ||
messages: DryvServerErrors; | ||
}; | ||
export type DryvServerValidationResponse = | ||
| any | ||
| { | ||
success: boolean | ||
messages: DryvServerErrors | ||
} | ||
export interface DryvServerErrors { | ||
[field: string]: DryvFieldValidationResult; | ||
[field: string]: DryvFieldValidationResult | ||
} | ||
export interface FieldEvent<TModel> { | ||
oldValue: any | ||
newValue: any | ||
field: keyof TModel | ||
} | ||
export type DryvValidationField<TValue = object> = { | ||
path: string | ||
type: DryvValidationResultType | null | ||
text: string | null | ||
group: string | null | ||
groupShown: boolean | ||
success: boolean | ||
hasErrors: boolean | ||
hasWarnings: boolean | ||
warningHash: string | undefined | null | ||
value: TValue | ||
validate(): Promise<DryvValidationResult> | ||
} | ||
export type DryvEditingObject<TModel extends object> = { | ||
[Property in keyof TModel]: TModel[Property] extends object | ||
? DryvEditingObject<TModel[Property]> | ||
: DryvValidationField<TModel[Property]> | ||
} |
@@ -1,2 +0,13 @@ | ||
export * from './core'; | ||
export * from './transaction'; | ||
export * from './DryvValidationSession'; | ||
export * from './dryvRuleSet'; | ||
export * from './typings'; | ||
export * from './DryvFieldValidator'; | ||
export * from './DryvObjectValidator'; | ||
export * from './DryvArrayValidator'; | ||
export * from './DryvComplexValidator'; | ||
export * from './DryvValidator'; | ||
export * from './defaultDryvOptions'; | ||
export * from './dryvOptions'; | ||
export * from './DryvValidationSession'; | ||
export * from './createValidator'; | ||
export * from "./type-checks"; |
@@ -1,3 +0,14 @@ | ||
export * from './core'; | ||
export * from './transaction'; | ||
export * from './DryvValidationSession'; | ||
export * from './dryvRuleSet'; | ||
export * from './typings'; | ||
export * from './DryvFieldValidator'; | ||
export * from './DryvObjectValidator'; | ||
export * from './DryvArrayValidator'; | ||
export * from './DryvComplexValidator'; | ||
export * from './DryvValidator'; | ||
export * from './defaultDryvOptions'; | ||
export * from './dryvOptions'; | ||
export * from './DryvValidationSession'; | ||
export * from './createValidator'; | ||
export * from "./type-checks"; | ||
//# sourceMappingURL=index.js.map |
@@ -1,8 +0,15 @@ | ||
import { DryvOptions } from '../core'; | ||
export interface DryvTransactionOptions { | ||
reactiveWrapper?<TObject>(object: TObject): TObject | ||
changeHook?(model: any, field: string, newValue: any, oldValue: any): void | ||
} | ||
export interface DryTransaction<TModel extends object = any> { | ||
rollback: () => void; | ||
commit: () => void; | ||
model: TModel; | ||
dirty: () => boolean; | ||
rollback: () => void | ||
commit: () => void | ||
model: TModel | ||
dirty: () => boolean | ||
} | ||
export declare function dryvTransaction<TModel extends object>(model: TModel, options?: DryvOptions): DryTransaction<TModel>; | ||
export declare function dryvTransaction<TModel extends object>( | ||
model: TModel, | ||
options?: DryvTransactionOptions | ||
): DryTransaction<TModel> | ||
export declare function isDryvTransaction(obj: any): boolean |
import { defaultDryvOptions } from '../core'; | ||
export function dryvTransaction(model, options) { | ||
options = Object.assign(defaultDryvOptions, options); | ||
const originalValues = Object.assign({}, model); | ||
const originalKeys = Object.keys(model).reduce((acc, key) => { | ||
acc[key] = true; | ||
return acc; | ||
}, {}); | ||
const values = options.objectWrapper(Object.assign({}, model)); | ||
const dirty = options.objectWrapper({ value: false }); | ||
let dirtyFields = {}; | ||
const proxy = new Proxy(model, { | ||
get(target, prop, receiver) { | ||
var _a; | ||
return (_a = values[prop]) !== null && _a !== void 0 ? _a : Reflect.get(target, prop, receiver); | ||
}, | ||
set(_, fieldName, value) { | ||
var _a; | ||
const field = fieldName; | ||
if (typeof originalValues[field] !== 'object' && typeof value !== 'object') { | ||
dirtyFields[String(fieldName)] = value !== originalValues[field]; | ||
} | ||
values[field] = value; | ||
dirty.value = (_a = Object.values(dirtyFields).find((x) => x)) !== null && _a !== void 0 ? _a : false; | ||
return true; | ||
} | ||
}); | ||
options = Object.assign({}, defaultDryvOptions, options); | ||
const handlers = options.objectWrapper([]); | ||
const proxy = new Proxy(model, new DryvTransactionProxyHandler(model, options, handlers)); | ||
return { | ||
commit() { | ||
Object.assign(model, values); | ||
dirtyFields = {}; | ||
dirty.value = false; | ||
handlers.forEach((handler) => handler.commit()); | ||
}, | ||
rollback() { | ||
Object.assign(values, model); | ||
Object.keys(values) | ||
.filter((key) => !originalKeys[key]) | ||
.forEach((key) => (values[key] = undefined)); | ||
dirtyFields = {}; | ||
dirty.value = false; | ||
handlers.forEach((handler) => handler.rollback()); | ||
}, | ||
model: proxy, | ||
dirty() { | ||
return dirty.value; | ||
return handlers.some((handler) => handler.dirty.value); | ||
} | ||
}; | ||
} | ||
export function isDryvTransaction(obj) { | ||
return obj && obj[DryvTransactionProxyHandler.isTransactionProp]; | ||
} | ||
class DryvTransactionProxyHandler { | ||
constructor(model, options, handlers) { | ||
this.model = model; | ||
this.options = options; | ||
this.handlers = handlers; | ||
this.dirtyFields = {}; | ||
handlers.push(this); | ||
this.dirty = this.options.objectWrapper({ value: false }); | ||
this.originalValues = Object.assign({}, model); | ||
this.originalKeys = Object.keys(model).reduce((acc, key) => { | ||
acc[key] = true; | ||
return acc; | ||
}, {}); | ||
const values = Object.keys(model).reduce((acc, key) => { | ||
const value = model[key]; | ||
acc[key] = | ||
!!value && typeof value === 'object' && !Array.isArray(value) | ||
? new Proxy(value, new DryvTransactionProxyHandler(value, this.options, this.handlers)) | ||
: value; | ||
return acc; | ||
}, {}); | ||
this.values = this.options.objectWrapper(values); | ||
} | ||
get(target, prop, receiver) { | ||
var _a; | ||
return prop === DryvTransactionProxyHandler.isTransactionProp | ||
? true | ||
: (_a = this.values[prop]) !== null && _a !== void 0 ? _a : Reflect.get(target, prop, receiver); | ||
} | ||
set(target, prop, value) { | ||
var _a, _b, _c; | ||
const field = prop; | ||
const isTransaction = isDryvTransaction(value); | ||
const isObject = !!value && typeof value === 'object'; | ||
if (isObject && !isTransaction && !Array.isArray(value)) { | ||
value = new Proxy(value, new DryvTransactionProxyHandler(value, this.options, this.handlers)); | ||
} | ||
const oldValue = this.values[field]; | ||
this.values[field] = value; | ||
if (!isObject) { | ||
this.dirtyFields[String(prop)] = value !== this.originalValues[field]; | ||
this.dirty.value = (_a = Object.values(this.dirtyFields).find((x) => x)) !== null && _a !== void 0 ? _a : false; | ||
(_c = (_b = this.options).changeHook) === null || _c === void 0 ? void 0 : _c.call(_b, this.model, field, value, oldValue); | ||
} | ||
return true; | ||
} | ||
commit() { | ||
Object.assign(this.model, this.values); | ||
this.dirtyFields = {}; | ||
this.dirty.value = false; | ||
} | ||
rollback() { | ||
Object.assign(this.values, this.model); | ||
Object.keys(this.values) | ||
.filter((key) => !this.originalKeys[key]) | ||
.forEach((key) => (this.values[key] = undefined)); | ||
this.dirtyFields = {}; | ||
this.dirty.value = false; | ||
} | ||
} | ||
DryvTransactionProxyHandler.isTransactionProp = '____trans'; | ||
//# sourceMappingURL=index.js.map |
{ | ||
"name": "dryvjs", | ||
"version": "1.0.0-pre-6", | ||
"version": "1.0.0-pre-60", | ||
"main": "dist/index.js", | ||
@@ -12,3 +12,3 @@ "types": "dist/index.d.ts", | ||
"dev": "tsc && (concurrently \"tsc -w\" \"tsc-alias -w\")", | ||
"build": "tsc", | ||
"build": "tsc && tsc-alias", | ||
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore", | ||
@@ -25,5 +25,5 @@ "format": "prettier --write src/" | ||
"prettier": "^3.0.3", | ||
"tsc-alias": "^1.8.8", | ||
"tsc-alias": "^1.8.10", | ||
"typescript": "~5.2.0" | ||
} | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
459415
338
6762
4