@vidyano-labs/virtual-service 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -2
- package/index.d.ts +68 -59
- package/index.js +67 -27
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -336,8 +336,10 @@ console.log(contact.getAttribute("Email").validationError);
|
|
|
336
336
|
Register your own validation rules for domain-specific requirements:
|
|
337
337
|
|
|
338
338
|
```typescript
|
|
339
|
+
import type { RuleValidationContext } from "@vidyano-labs/virtual-service";
|
|
340
|
+
|
|
339
341
|
// Register a custom rule (before registerPersistentObject)
|
|
340
|
-
service.registerBusinessRule("IsPhoneNumber", (value: any) => {
|
|
342
|
+
service.registerBusinessRule("IsPhoneNumber", (value: any, context: RuleValidationContext) => {
|
|
341
343
|
if (value == null || value === "") return;
|
|
342
344
|
const phoneRegex = /^\+?[\d\s-()]+$/;
|
|
343
345
|
if (!phoneRegex.test(String(value)))
|
|
@@ -357,8 +359,39 @@ service.registerPersistentObject({
|
|
|
357
359
|
});
|
|
358
360
|
```
|
|
359
361
|
|
|
362
|
+
**Validation context:**
|
|
363
|
+
The `RuleValidationContext` parameter provides access to:
|
|
364
|
+
- `context.persistentObject` - The persistent object being validated (wrapped with helper methods)
|
|
365
|
+
- `context.attribute` - The attribute being validated (wrapped with helper methods)
|
|
366
|
+
|
|
367
|
+
This allows cross-field validation:
|
|
368
|
+
|
|
369
|
+
```typescript
|
|
370
|
+
// Validate password confirmation matches password
|
|
371
|
+
service.registerBusinessRule("MatchesPassword", (value: any, context: RuleValidationContext) => {
|
|
372
|
+
if (!value) return;
|
|
373
|
+
|
|
374
|
+
const passwordValue = context.persistentObject.getAttributeValue("Password");
|
|
375
|
+
if (value !== passwordValue)
|
|
376
|
+
throw new Error("Passwords do not match");
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
service.registerPersistentObject({
|
|
380
|
+
type: "User",
|
|
381
|
+
attributes: [
|
|
382
|
+
{ name: "Password", type: "String" },
|
|
383
|
+
{
|
|
384
|
+
name: "ConfirmPassword",
|
|
385
|
+
type: "String",
|
|
386
|
+
rules: "MatchesPassword"
|
|
387
|
+
}
|
|
388
|
+
]
|
|
389
|
+
});
|
|
390
|
+
```
|
|
391
|
+
|
|
360
392
|
**Custom rule requirements:**
|
|
361
393
|
- Must be registered before `registerPersistentObject()`
|
|
394
|
+
- Receives two parameters: `value` (the attribute value) and `context` (validation context)
|
|
362
395
|
- Throw an `Error` with a message if validation fails
|
|
363
396
|
- Return nothing (or undefined) if validation passes
|
|
364
397
|
- Cannot override built-in rules
|
|
@@ -1097,7 +1130,8 @@ import type {
|
|
|
1097
1130
|
ActionHandler,
|
|
1098
1131
|
ActionArgs,
|
|
1099
1132
|
ActionContext,
|
|
1100
|
-
RuleValidatorFn
|
|
1133
|
+
RuleValidatorFn,
|
|
1134
|
+
RuleValidationContext
|
|
1101
1135
|
} from "@vidyano-labs/virtual-service";
|
|
1102
1136
|
```
|
|
1103
1137
|
|
package/index.d.ts
CHANGED
|
@@ -1,5 +1,58 @@
|
|
|
1
1
|
import { Dto, ServiceHooks, Service, Application } from '@vidyano/core';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* VirtualPersistentObjectAttribute combines a PersistentObjectAttributeDto with helper methods
|
|
5
|
+
* This allows clean syntax like attr.getValue() and attr.setValue() while keeping the underlying DTO unchanged
|
|
6
|
+
*/
|
|
7
|
+
type VirtualPersistentObjectAttribute = Dto.PersistentObjectAttributeDto & {
|
|
8
|
+
/**
|
|
9
|
+
* Gets the converted value of this attribute (e.g., Boolean as boolean, Int32 as number)
|
|
10
|
+
*/
|
|
11
|
+
getValue(): any;
|
|
12
|
+
/**
|
|
13
|
+
* Sets the value of this attribute with automatic type conversion
|
|
14
|
+
*/
|
|
15
|
+
setValue(value: any): void;
|
|
16
|
+
/**
|
|
17
|
+
* Sets a validation error on this attribute
|
|
18
|
+
*/
|
|
19
|
+
setValidationError(error: string): void;
|
|
20
|
+
/**
|
|
21
|
+
* Clears the validation error on this attribute
|
|
22
|
+
*/
|
|
23
|
+
clearValidationError(): void;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* VirtualPersistentObject combines a PersistentObjectDto with helper methods
|
|
27
|
+
* This allows clean syntax like obj.setAttributeValue() while keeping the underlying DTO unchanged
|
|
28
|
+
*/
|
|
29
|
+
type VirtualPersistentObject = Dto.PersistentObjectDto & {
|
|
30
|
+
/**
|
|
31
|
+
* Gets an attribute by name, wrapped with getValue/setValue methods
|
|
32
|
+
*/
|
|
33
|
+
getAttribute(name: string): VirtualPersistentObjectAttribute | undefined;
|
|
34
|
+
/**
|
|
35
|
+
* Gets the value of an attribute by name
|
|
36
|
+
*/
|
|
37
|
+
getAttributeValue(name: string): any;
|
|
38
|
+
/**
|
|
39
|
+
* Sets the value of an attribute by name
|
|
40
|
+
*/
|
|
41
|
+
setAttributeValue(name: string, value: any): void;
|
|
42
|
+
/**
|
|
43
|
+
* Sets a validation error for an attribute
|
|
44
|
+
*/
|
|
45
|
+
setValidationError(name: string, error: string): void;
|
|
46
|
+
/**
|
|
47
|
+
* Clears a validation error for an attribute
|
|
48
|
+
*/
|
|
49
|
+
clearValidationError(name: string): void;
|
|
50
|
+
/**
|
|
51
|
+
* Sets a notification message on the persistent object
|
|
52
|
+
*/
|
|
53
|
+
setNotification(message: string, type: Dto.NotificationType, duration?: number): void;
|
|
54
|
+
};
|
|
55
|
+
|
|
3
56
|
/**
|
|
4
57
|
* Simplified attribute configuration - converted to PersistentObjectAttributeDto
|
|
5
58
|
*/
|
|
@@ -24,10 +77,6 @@ type VirtualPersistentObjectAttributeConfig = {
|
|
|
24
77
|
* Initial value for the attribute.
|
|
25
78
|
*/
|
|
26
79
|
value?: any;
|
|
27
|
-
/**
|
|
28
|
-
* Indicates whether this attribute is required. Defaults to false.
|
|
29
|
-
*/
|
|
30
|
-
isRequired?: boolean;
|
|
31
80
|
/**
|
|
32
81
|
* Indicates whether the value of this attribute can be changed. Defaults to false.
|
|
33
82
|
*/
|
|
@@ -184,6 +233,19 @@ type ActionContext = {
|
|
|
184
233
|
*/
|
|
185
234
|
setNotification: (message: string, type: Dto.NotificationType, duration?: number) => void;
|
|
186
235
|
};
|
|
236
|
+
/**
|
|
237
|
+
* Context provided to business rule validators for accessing the persistent object
|
|
238
|
+
*/
|
|
239
|
+
type RuleValidationContext = {
|
|
240
|
+
/**
|
|
241
|
+
* The persistent object being validated (wrapped with helper methods)
|
|
242
|
+
*/
|
|
243
|
+
persistentObject: VirtualPersistentObject;
|
|
244
|
+
/**
|
|
245
|
+
* The attribute being validated (wrapped with helper methods)
|
|
246
|
+
*/
|
|
247
|
+
attribute: VirtualPersistentObjectAttribute;
|
|
248
|
+
};
|
|
187
249
|
/**
|
|
188
250
|
* PersistentObject configuration - converted to PersistentObjectDto
|
|
189
251
|
*/
|
|
@@ -286,60 +348,7 @@ type VirtualQueryConfig = {
|
|
|
286
348
|
/**
|
|
287
349
|
* Rule validator function that throws an error if invalid, or returns nothing if valid
|
|
288
350
|
*/
|
|
289
|
-
type RuleValidatorFn = (value: any, ...params: any[]) => void;
|
|
290
|
-
|
|
291
|
-
/**
|
|
292
|
-
* VirtualPersistentObjectAttribute combines a PersistentObjectAttributeDto with helper methods
|
|
293
|
-
* This allows clean syntax like attr.getValue() and attr.setValue() while keeping the underlying DTO unchanged
|
|
294
|
-
*/
|
|
295
|
-
type VirtualPersistentObjectAttribute = Dto.PersistentObjectAttributeDto & {
|
|
296
|
-
/**
|
|
297
|
-
* Gets the converted value of this attribute (e.g., Boolean as boolean, Int32 as number)
|
|
298
|
-
*/
|
|
299
|
-
getValue(): any;
|
|
300
|
-
/**
|
|
301
|
-
* Sets the value of this attribute with automatic type conversion
|
|
302
|
-
*/
|
|
303
|
-
setValue(value: any): void;
|
|
304
|
-
/**
|
|
305
|
-
* Sets a validation error on this attribute
|
|
306
|
-
*/
|
|
307
|
-
setValidationError(error: string): void;
|
|
308
|
-
/**
|
|
309
|
-
* Clears the validation error on this attribute
|
|
310
|
-
*/
|
|
311
|
-
clearValidationError(): void;
|
|
312
|
-
};
|
|
313
|
-
/**
|
|
314
|
-
* VirtualPersistentObject combines a PersistentObjectDto with helper methods
|
|
315
|
-
* This allows clean syntax like obj.setAttributeValue() while keeping the underlying DTO unchanged
|
|
316
|
-
*/
|
|
317
|
-
type VirtualPersistentObject = Dto.PersistentObjectDto & {
|
|
318
|
-
/**
|
|
319
|
-
* Gets an attribute by name, wrapped with getValue/setValue methods
|
|
320
|
-
*/
|
|
321
|
-
getAttribute(name: string): VirtualPersistentObjectAttribute | undefined;
|
|
322
|
-
/**
|
|
323
|
-
* Gets the value of an attribute by name
|
|
324
|
-
*/
|
|
325
|
-
getAttributeValue(name: string): any;
|
|
326
|
-
/**
|
|
327
|
-
* Sets the value of an attribute by name
|
|
328
|
-
*/
|
|
329
|
-
setAttributeValue(name: string, value: any): void;
|
|
330
|
-
/**
|
|
331
|
-
* Sets a validation error for an attribute
|
|
332
|
-
*/
|
|
333
|
-
setValidationError(name: string, error: string): void;
|
|
334
|
-
/**
|
|
335
|
-
* Clears a validation error for an attribute
|
|
336
|
-
*/
|
|
337
|
-
clearValidationError(name: string): void;
|
|
338
|
-
/**
|
|
339
|
-
* Sets a notification message on the persistent object
|
|
340
|
-
*/
|
|
341
|
-
setNotification(message: string, type: Dto.NotificationType, duration?: number): void;
|
|
342
|
-
};
|
|
351
|
+
type RuleValidatorFn = (value: any, context: RuleValidationContext, ...params: any[]) => void;
|
|
343
352
|
|
|
344
353
|
/**
|
|
345
354
|
* Base class for PersistentObject lifecycle methods
|
|
@@ -556,4 +565,4 @@ declare class VirtualService extends Service {
|
|
|
556
565
|
}
|
|
557
566
|
|
|
558
567
|
export { VirtualPersistentObjectActions, VirtualService, VirtualServiceHooks };
|
|
559
|
-
export type { ActionArgs, ActionConfig, ActionContext, ActionHandler, RuleValidatorFn, VirtualPersistentObject, VirtualPersistentObjectAttribute, VirtualPersistentObjectAttributeConfig, VirtualPersistentObjectConfig, VirtualQueryConfig, VirtualQueryExecuteResult };
|
|
568
|
+
export type { ActionArgs, ActionConfig, ActionContext, ActionHandler, RuleValidationContext, RuleValidatorFn, VirtualPersistentObject, VirtualPersistentObjectAttribute, VirtualPersistentObjectAttributeConfig, VirtualPersistentObjectConfig, VirtualQueryConfig, VirtualQueryExecuteResult };
|
package/index.js
CHANGED
|
@@ -215,18 +215,18 @@ class VirtualPersistentObjectRegistry {
|
|
|
215
215
|
for (const attr of po.attributes) {
|
|
216
216
|
// Clear previous validation errors
|
|
217
217
|
attr.validationError = undefined;
|
|
218
|
-
// Find the attribute config to get rules
|
|
218
|
+
// Find the attribute config to get rules
|
|
219
219
|
const attrConfig = config.attributes.find(a => a.name === attr.name);
|
|
220
220
|
if (!attrConfig)
|
|
221
221
|
continue;
|
|
222
|
-
//
|
|
222
|
+
// Always use server config for rules and isRequired (never trust client values)
|
|
223
223
|
const attrWithRules = {
|
|
224
224
|
...attr,
|
|
225
225
|
rules: attrConfig.rules,
|
|
226
|
-
isRequired: attrConfig.
|
|
226
|
+
isRequired: hasRequiredRule(attrConfig.rules)
|
|
227
227
|
};
|
|
228
228
|
// Validate the attribute
|
|
229
|
-
const error = this.#validator.validateAttribute(attrWithRules);
|
|
229
|
+
const error = this.#validator.validateAttribute(attrWithRules, po);
|
|
230
230
|
if (error) {
|
|
231
231
|
attr.validationError = error;
|
|
232
232
|
hasErrors = true;
|
|
@@ -345,17 +345,36 @@ async function buildPersistentObjectDto(config, queryRegistry, objectId, isNew)
|
|
|
345
345
|
queries
|
|
346
346
|
};
|
|
347
347
|
}
|
|
348
|
+
/**
|
|
349
|
+
* Checks if rules string contains NotEmpty or Required
|
|
350
|
+
*/
|
|
351
|
+
function hasRequiredRule(rules) {
|
|
352
|
+
if (!rules)
|
|
353
|
+
return false;
|
|
354
|
+
// Parse the rules string (semicolon-separated)
|
|
355
|
+
const ruleNames = rules
|
|
356
|
+
.split(";")
|
|
357
|
+
.map(rule => rule.trim())
|
|
358
|
+
.map(rule => {
|
|
359
|
+
// Extract just the rule name (before any parentheses)
|
|
360
|
+
const match = rule.match(/^(\w+)/);
|
|
361
|
+
return match ? match[1] : "";
|
|
362
|
+
});
|
|
363
|
+
return ruleNames.includes("NotEmpty") || ruleNames.includes("Required");
|
|
364
|
+
}
|
|
348
365
|
/**
|
|
349
366
|
* Builds a PersistentObjectAttributeDto from configuration
|
|
350
367
|
*/
|
|
351
368
|
async function buildAttributeDto(config, index, queryRegistry) {
|
|
369
|
+
// Automatically set isRequired if rules contain NotEmpty or Required
|
|
370
|
+
const isRequired = hasRequiredRule(config.rules);
|
|
352
371
|
const baseDto = {
|
|
353
372
|
id: config.id || crypto.randomUUID(),
|
|
354
373
|
name: config.name,
|
|
355
374
|
type: config.type || "String",
|
|
356
375
|
label: config.label || config.name,
|
|
357
376
|
value: config.value,
|
|
358
|
-
isRequired
|
|
377
|
+
isRequired,
|
|
359
378
|
isReadOnly: config.isReadOnly || false,
|
|
360
379
|
rules: config.rules,
|
|
361
380
|
visibility: config.visibility || "Always",
|
|
@@ -1221,7 +1240,7 @@ class BusinessRuleValidator {
|
|
|
1221
1240
|
this.#builtInRules.set("MinLength", this.#validateMinLength.bind(this));
|
|
1222
1241
|
this.#builtInRules.set("MinValue", this.#validateMinValue.bind(this));
|
|
1223
1242
|
this.#builtInRules.set("NotEmpty", this.#validateNotEmpty.bind(this));
|
|
1224
|
-
this.#builtInRules.set("Required", this.#
|
|
1243
|
+
this.#builtInRules.set("Required", this.#validateRequired.bind(this));
|
|
1225
1244
|
}
|
|
1226
1245
|
/**
|
|
1227
1246
|
* Register a custom business rule
|
|
@@ -1234,19 +1253,32 @@ class BusinessRuleValidator {
|
|
|
1234
1253
|
}
|
|
1235
1254
|
/**
|
|
1236
1255
|
* Validate an attribute against its rules
|
|
1256
|
+
* @param attr - The attribute to validate
|
|
1257
|
+
* @param po - The persistent object containing the attribute
|
|
1237
1258
|
* @returns Error message if validation fails, null if valid
|
|
1238
1259
|
*/
|
|
1239
|
-
validateAttribute(attr) {
|
|
1240
|
-
//
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
return error instanceof Error ? error.message : String(error);
|
|
1260
|
+
validateAttribute(attr, po) {
|
|
1261
|
+
// Create conversion context for wrappers
|
|
1262
|
+
const conversionContext = {
|
|
1263
|
+
getConvertedValue: (attribute) => this.#getConvertedValue(attribute),
|
|
1264
|
+
setConvertedValue: (attribute, value) => {
|
|
1265
|
+
attribute.value = toServiceValue(value, attribute.type);
|
|
1266
|
+
attribute.isValueChanged = true;
|
|
1247
1267
|
}
|
|
1248
|
-
}
|
|
1268
|
+
};
|
|
1269
|
+
// Create wrapped objects for the validation context
|
|
1270
|
+
const wrappedPo = createVirtualPersistentObject(po, conversionContext);
|
|
1271
|
+
const wrappedAttr = createVirtualPersistentObjectAttribute(attr, conversionContext);
|
|
1272
|
+
// Create validation context
|
|
1273
|
+
const context = {
|
|
1274
|
+
persistentObject: wrappedPo,
|
|
1275
|
+
attribute: wrappedAttr
|
|
1276
|
+
};
|
|
1277
|
+
// Get the converted value (e.g., boolean from "True"/"False", number from string)
|
|
1278
|
+
const convertedValue = this.#getConvertedValue(attr);
|
|
1249
1279
|
// Parse and validate rules string
|
|
1280
|
+
// Note: isRequired is auto-set from rules for UI purposes only (e.g., showing asterisks)
|
|
1281
|
+
// All validation logic is handled by the rules themselves
|
|
1250
1282
|
if (!attr.rules)
|
|
1251
1283
|
return null;
|
|
1252
1284
|
const rules = this.parseRules(attr.rules);
|
|
@@ -1255,7 +1287,7 @@ class BusinessRuleValidator {
|
|
|
1255
1287
|
if (!validator)
|
|
1256
1288
|
throw new Error(`Unknown business rule: ${rule.name}`);
|
|
1257
1289
|
try {
|
|
1258
|
-
validator(
|
|
1290
|
+
validator(convertedValue, context, ...rule.params);
|
|
1259
1291
|
}
|
|
1260
1292
|
catch (error) {
|
|
1261
1293
|
return error instanceof Error ? error.message : String(error);
|
|
@@ -1308,15 +1340,19 @@ class BusinessRuleValidator {
|
|
|
1308
1340
|
});
|
|
1309
1341
|
return { name, params };
|
|
1310
1342
|
}
|
|
1343
|
+
// Helper to convert attribute values based on type
|
|
1344
|
+
#getConvertedValue(attr) {
|
|
1345
|
+
return fromServiceValue(attr.value, attr.type);
|
|
1346
|
+
}
|
|
1311
1347
|
// Built-in validators - throw errors instead of returning strings
|
|
1312
|
-
#validateIsBase64(value) {
|
|
1348
|
+
#validateIsBase64(value, context) {
|
|
1313
1349
|
if (value == null || value === "")
|
|
1314
1350
|
return;
|
|
1315
1351
|
const base64Regex = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;
|
|
1316
1352
|
if (!base64Regex.test(String(value)))
|
|
1317
1353
|
throw new Error("Value must be a valid base64 string");
|
|
1318
1354
|
}
|
|
1319
|
-
#validateIsEmail(value) {
|
|
1355
|
+
#validateIsEmail(value, context) {
|
|
1320
1356
|
if (value == null || value === "")
|
|
1321
1357
|
return;
|
|
1322
1358
|
// Only allow ASCII characters in email addresses
|
|
@@ -1324,7 +1360,7 @@ class BusinessRuleValidator {
|
|
|
1324
1360
|
if (!emailRegex.test(String(value)))
|
|
1325
1361
|
throw new Error("Email format is invalid");
|
|
1326
1362
|
}
|
|
1327
|
-
#validateIsRegex(value) {
|
|
1363
|
+
#validateIsRegex(value, context) {
|
|
1328
1364
|
if (value == null || value === "")
|
|
1329
1365
|
return;
|
|
1330
1366
|
try {
|
|
@@ -1334,7 +1370,7 @@ class BusinessRuleValidator {
|
|
|
1334
1370
|
throw new Error("Value must be a valid regular expression");
|
|
1335
1371
|
}
|
|
1336
1372
|
}
|
|
1337
|
-
#validateIsUrl(value) {
|
|
1373
|
+
#validateIsUrl(value, context) {
|
|
1338
1374
|
if (value == null || value === "")
|
|
1339
1375
|
return;
|
|
1340
1376
|
try {
|
|
@@ -1344,21 +1380,21 @@ class BusinessRuleValidator {
|
|
|
1344
1380
|
throw new Error("Value must be a valid URL");
|
|
1345
1381
|
}
|
|
1346
1382
|
}
|
|
1347
|
-
#validateIsWord(value) {
|
|
1383
|
+
#validateIsWord(value, context) {
|
|
1348
1384
|
if (value == null || value === "")
|
|
1349
1385
|
return;
|
|
1350
1386
|
const wordRegex = /^\w+$/;
|
|
1351
1387
|
if (!wordRegex.test(String(value)))
|
|
1352
1388
|
throw new Error("Value must contain only word characters");
|
|
1353
1389
|
}
|
|
1354
|
-
#validateMaxLength(value, maxLength) {
|
|
1390
|
+
#validateMaxLength(value, context, maxLength) {
|
|
1355
1391
|
if (value == null || value === "")
|
|
1356
1392
|
return;
|
|
1357
1393
|
const length = String(value).length;
|
|
1358
1394
|
if (length > maxLength)
|
|
1359
1395
|
throw new Error(`Maximum length is ${maxLength} characters`);
|
|
1360
1396
|
}
|
|
1361
|
-
#validateMaxValue(value, maximum) {
|
|
1397
|
+
#validateMaxValue(value, context, maximum) {
|
|
1362
1398
|
if (value == null || value === "")
|
|
1363
1399
|
return;
|
|
1364
1400
|
const num = Number(value);
|
|
@@ -1367,14 +1403,14 @@ class BusinessRuleValidator {
|
|
|
1367
1403
|
if (num > maximum)
|
|
1368
1404
|
throw new Error(`Maximum value is ${maximum}`);
|
|
1369
1405
|
}
|
|
1370
|
-
#validateMinLength(value, minLength) {
|
|
1406
|
+
#validateMinLength(value, context, minLength) {
|
|
1371
1407
|
if (value == null || value === "")
|
|
1372
1408
|
return;
|
|
1373
1409
|
const length = String(value).length;
|
|
1374
1410
|
if (length < minLength)
|
|
1375
1411
|
throw new Error(`Minimum length is ${minLength} characters`);
|
|
1376
1412
|
}
|
|
1377
|
-
#validateMinValue(value, minimum) {
|
|
1413
|
+
#validateMinValue(value, context, minimum) {
|
|
1378
1414
|
if (value == null || value === "")
|
|
1379
1415
|
return;
|
|
1380
1416
|
const num = Number(value);
|
|
@@ -1383,10 +1419,14 @@ class BusinessRuleValidator {
|
|
|
1383
1419
|
if (num < minimum)
|
|
1384
1420
|
throw new Error(`Minimum value is ${minimum}`);
|
|
1385
1421
|
}
|
|
1386
|
-
#
|
|
1387
|
-
if (value == null
|
|
1422
|
+
#validateRequired(value, context) {
|
|
1423
|
+
if (value == null)
|
|
1388
1424
|
throw new Error("This field is required");
|
|
1389
1425
|
}
|
|
1426
|
+
#validateNotEmpty(value, context) {
|
|
1427
|
+
if (value == null || value === "" || (typeof value === "string" && value.trim() === ""))
|
|
1428
|
+
throw new Error("This field cannot be empty");
|
|
1429
|
+
}
|
|
1390
1430
|
}
|
|
1391
1431
|
|
|
1392
1432
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vidyano-labs/virtual-service",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Virtual service implementation for testing Vidyano applications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
@@ -20,5 +20,5 @@
|
|
|
20
20
|
"publishConfig": {
|
|
21
21
|
"access": "public"
|
|
22
22
|
},
|
|
23
|
-
"gitHash": "
|
|
23
|
+
"gitHash": "a8a427169445d844bc42c226c93da215441e6242"
|
|
24
24
|
}
|