UNPKG

@mahmoudxyz/hassan

Version:

Type-safe data mapper for TypeScript with zero runtime overhead

115 lines 3.55 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.h = void 0; exports.createMapper = createMapper; exports.h = { direct: (value) => ({ __type: 'direct', value, }), when: (condition, thenValue, elseValue) => { const mapping = { __type: 'conditional', when: condition, then: thenValue, }; if (elseValue !== undefined) { mapping.else = elseValue; } return mapping; }, }; const isValidObject = (input) => { return input !== null && typeof input === 'object' && !Array.isArray(input); }; const isDirectValue = (value) => { return (typeof value === 'object' && value !== null && value.__type === 'direct'); }; const isConditionalMapping = (value) => { return (typeof value === 'object' && value !== null && value.__type === 'conditional'); }; const isTransformFunction = (value) => { return typeof value === 'function'; }; const setNestedProperty = (obj, path, value) => { const keys = path.split('.'); let current = obj; for (let i = 0; i < keys.length - 1; i++) { const key = keys[i]; if (!(key in current) || !isValidObject(current[key])) { current[key] = {}; } current = current[key]; } current[keys[keys.length - 1]] = value; }; const getNestedProperty = (obj, path) => { const keys = path.split('.'); let current = obj; for (const key of keys) { if (!isValidObject(current) || !(key in current)) { return undefined; } current = current[key]; } return current; }; const resolveMappingValue = (source, mapping, context) => { if (isDirectValue(mapping)) { return mapping.value; } if (isTransformFunction(mapping)) { return mapping(source, context); } if (mapping.includes('.')) { return getNestedProperty(source, mapping); } return source[mapping]; }; const mapProperty = (source, targetKey, mapping, context) => { if (isConditionalMapping(mapping)) { const conditionResult = mapping.when(source, context); if (conditionResult) { const resolvedValue = resolveMappingValue(source, mapping.then, context); return [targetKey, resolvedValue]; } else if (mapping.else !== undefined) { const resolvedValue = resolveMappingValue(source, mapping.else, context); return [targetKey, resolvedValue]; } return null; } const resolvedValue = resolveMappingValue(source, mapping, context); return resolvedValue !== undefined ? [targetKey, resolvedValue] : null; }; const buildMappedObject = (source, mappings, context) => { const result = {}; for (const [targetKey, mapping] of Object.entries(mappings)) { const mappedProperty = mapProperty(source, targetKey, mapping, context); if (mappedProperty !== null) { const [key, value] = mappedProperty; if (key.includes('.')) { setNestedProperty(result, key, value); } else { result[key] = value; } } } return result; }; function createMapper(mappings) { return { map: (input, context) => { if (!isValidObject(input)) { return input; } return buildMappedObject(input, mappings, context); }, }; } //# sourceMappingURL=mapper.js.map