monte-carlo-simulator
Version:
Business decision framework with Monte Carlo risk analysis - instant via npx
177 lines • 6.91 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ConfigurationValidator = void 0;
const ajv_1 = __importDefault(require("ajv"));
const parameterSchema = {
type: 'object',
properties: {
key: { type: 'string', minLength: 1 },
label: { type: 'string', minLength: 1 },
type: { type: 'string', enum: ['number', 'boolean', 'string', 'select'] },
default: { type: ['number', 'boolean', 'string'] },
min: { type: 'number', nullable: true },
max: { type: 'number', nullable: true },
step: { type: 'number', nullable: true },
options: {
type: 'array',
items: { type: 'string' },
nullable: true
},
description: { type: 'string', nullable: true }
},
required: ['key', 'label', 'type', 'default'],
additionalProperties: false
};
const groupSchema = {
type: 'object',
properties: {
name: { type: 'string', minLength: 1 },
description: { type: 'string', nullable: true },
parameters: {
type: 'array',
items: { type: 'string' },
minItems: 1
}
},
required: ['name', 'parameters'],
additionalProperties: false
};
const outputSchema = {
type: 'object',
properties: {
key: { type: 'string', minLength: 1 },
label: { type: 'string', minLength: 1 },
type: { type: 'string', enum: ['number', 'boolean', 'string'], nullable: true },
description: { type: 'string', nullable: true }
},
required: ['key', 'label'],
additionalProperties: false
};
const simulationConfigSchema = {
type: 'object',
properties: {
name: { type: 'string', minLength: 1, maxLength: 100 },
category: { type: 'string', minLength: 1 },
description: { type: 'string', minLength: 10, maxLength: 500 },
version: { type: 'string', pattern: '^\\d+\\.\\d+\\.\\d+$' },
tags: {
type: 'array',
items: { type: 'string', minLength: 1 },
minItems: 1,
maxItems: 10
},
baseSimulation: { type: 'string', nullable: true },
businessContext: { type: 'boolean', nullable: true },
parameters: {
type: 'array',
items: parameterSchema,
minItems: 1,
maxItems: 20
},
groups: {
type: 'array',
items: groupSchema,
nullable: true
},
outputs: {
type: 'array',
items: outputSchema,
minItems: 1,
maxItems: 10,
nullable: true
},
simulation: {
type: 'object',
properties: {
logic: { type: 'string', minLength: 10 }
},
required: ['logic'],
additionalProperties: false,
nullable: true
}
},
required: ['name', 'category', 'description', 'version', 'tags', 'parameters'],
additionalProperties: false
};
class ConfigurationValidator {
ajv;
validate;
constructor() {
this.ajv = new ajv_1.default({ allowUnionTypes: true });
this.validate = this.ajv.compile(simulationConfigSchema);
}
validateConfig(config) {
const isValid = this.validate(config);
if (isValid) {
// Additional business logic validation
return this.validateBusinessRules(config);
}
const errors = this.ajv.errorsText(this.ajv.errors || []).split(', ');
return { valid: false, errors };
}
validateBusinessRules(config) {
const errors = [];
// Check for duplicate parameter keys
const paramKeys = config.parameters.map(p => p.key);
const duplicateKeys = paramKeys.filter((key, index) => paramKeys.indexOf(key) !== index);
if (duplicateKeys.length > 0) {
errors.push(`Duplicate parameter keys: ${duplicateKeys.join(', ')}`);
}
// Check for duplicate output keys (only if outputs exist)
if (config.outputs) {
const outputKeys = config.outputs.map(o => o.key);
const duplicateOutputs = outputKeys.filter((key, index) => outputKeys.indexOf(key) !== index);
if (duplicateOutputs.length > 0) {
errors.push(`Duplicate output keys: ${duplicateOutputs.join(', ')}`);
}
}
// Validate select parameters have options
config.parameters.forEach(param => {
if (param.type === 'select' && (!param.options || param.options.length === 0)) {
errors.push(`Select parameter '${param.key}' must have options`);
}
if (param.type === 'select' && param.options && !param.options.includes(String(param.default))) {
errors.push(`Default value for '${param.key}' must be one of the options`);
}
});
// Validate number parameter constraints
config.parameters.forEach(param => {
if (param.type === 'number') {
const defaultNum = Number(param.default);
if (param.min !== undefined && defaultNum < param.min) {
errors.push(`Default value for '${param.key}' is below minimum`);
}
if (param.max !== undefined && defaultNum > param.max) {
errors.push(`Default value for '${param.key}' is above maximum`);
}
}
});
// Validate groups reference existing parameters
if (config.groups) {
config.groups.forEach(group => {
group.parameters.forEach(paramKey => {
if (!paramKeys.includes(paramKey)) {
errors.push(`Group '${group.name}' references non-existent parameter '${paramKey}'`);
}
});
});
}
// Validate simulation logic contains return statement (only if simulation logic exists)
if (config.simulation && !config.simulation.logic.includes('return')) {
errors.push('Simulation logic must contain a return statement');
}
// Validate simulation logic references output keys (only if both exist)
if (config.simulation && config.outputs) {
const logicReferencesOutputs = config.outputs.some(output => config.simulation.logic.includes(output.key));
if (!logicReferencesOutputs) {
errors.push('Simulation logic should return at least one of the defined outputs');
}
}
return { valid: errors.length === 0, errors };
}
}
exports.ConfigurationValidator = ConfigurationValidator;
//# sourceMappingURL=schema.js.map