yini-parser
Version:
Readable configuration without YAML foot-guns or JSON noise. The official Node.js parser for YINI config format — An INI-inspired configuration format with clear nesting, explicit types, and predictable parsing.
114 lines • 4.38 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.matchModeFromCoreOptions = exports.matchModeFromParseOptions = void 0;
const env_1 = require("../../config/env");
const print_1 = require("../../utils/print");
const errorDataHandler_1 = require("../errorDataHandler");
const optionsFunctions_1 = require("../options/optionsFunctions");
const MODE_PROFILES = {
lenient: [0, 0, 0],
// moderate: [1, 0, 1],
strict: [2, 0, 2],
//'pedantic'
//'paranoid'
};
const matchModeFromParseOptions = (parserOptions) => (0, exports.matchModeFromCoreOptions)((0, optionsFunctions_1.toCoreOptions)(parserOptions));
exports.matchModeFromParseOptions = matchModeFromParseOptions;
/**
* Determines the effective parse mode from the current options (option rules).
* @returns 'custom' if no exact match exists, otherwise the matched mode.
*/
const matchModeFromCoreOptions = (coreOptions) => {
(0, print_1.debugPrint)('-> matchModeFromRules(..):');
if (!coreOptions?.rules) {
// Note, after pushing processing may continue or exit, depending on the error and/or the bail threshold.
new errorDataHandler_1.ErrorDataHandler('None/Ignore').pushOrBail(null, 'Fatal-Error', `The passed input object is missing rules object.`, 'Option might be of wrong type, it must be core options.');
}
// debugPrint(
// 'coreOptions.rules.?onDuplicateKey = ' +
// coreOptions.rules?.onDuplicateKey,
// )
// debugPrint(
// 'coreOptions.rules.?requireDocTerminator = ' +
// coreOptions.rules?.requireDocTerminator,
// )
// debugPrint(
// 'coreOptions.rules.?treatEmptyValueAsNull = ' +
// coreOptions.rules?.treatEmptyValueAsNull,
// )
const rules = { ...coreOptions.rules };
// if (rules.onDuplicateKey === 'error') {
// if (rules.treatEmptyValueAsNull == 'disallow') {
// return 'strict'
// }
// return 'lenient'
// }
// return 'custom'
const res = inferTParserModeExact(rules);
(0, print_1.debugPrint)(' mode = ' + res.mode);
(0, print_1.debugPrint)(' vector = ' + res.vector);
(0, print_1.debugPrint)('matchedProfile = ' + res.matchedProfile);
return res.mode;
};
exports.matchModeFromCoreOptions = matchModeFromCoreOptions;
/**
* Infer mode by **exact vector match** to a canonical profile (option rules).
* If no exact match exists, returns 'custom'.
*/
const inferTParserModeExact = (rules) => {
// debugPrint('-> inferTParserModeExact(..):')
// debugPrint('rules.onDuplicateKey = ' + rules.onDuplicateKey)
// debugPrint('rules.requireDocTerminator = ' + rules.requireDocTerminator)
// debugPrint('rules.treatEmptyValueAsNull = ' + rules.treatEmptyValueAsNull)
// Note, **each rule** is scored on a strictness scale (0 = lenient, 1 = medium, 2 = strict).
const vector = [
scoreDupl(rules.onDuplicateKey),
scoreTerm(rules.requireDocTerminator),
scoreEmpty(rules.treatEmptyValueAsNull),
];
(0, print_1.debugPrint)('** vector:');
// isDebug() && printObject(vector)
(0, env_1.isDebug)() && console.log(vector);
for (const mode of Object.keys(MODE_PROFILES)) {
if (vecEquals(vector, MODE_PROFILES[mode])) {
return { mode, vector, matchedProfile: mode };
}
}
return { mode: 'custom', vector };
};
const scoreDupl = (v) => {
switch (v) {
case 'keep-first':
case 'warn-and-keep-first':
return 0; // Rule in lenient mode.
case 'overwrite':
case 'warn-and-overwrite':
return 1;
case 'error':
return 2; // Rule in strict mode.
}
};
const scoreTerm = (v) => {
switch (v) {
case 'optional':
return 0; // Rule in lenient and strict mode.
case 'warn-if-missing':
return 1;
case 'required':
return 2;
}
};
const scoreEmpty = (v) => {
switch (v) {
case 'allow':
return 0; // Rule in lenient mode.
case 'allow-with-warning':
return 1;
case 'disallow':
return 2; // Rule in strict mode.
}
};
const vecEquals = (a, b) => {
return a[0] === b[0] && a[1] === b[1] && a[2] === b[2];
};
//# sourceMappingURL=modeFromRulesMatcher.js.map