"use strict"; const mapObj = require("map-obj"); const filterObj = require("filter-obj"); const typeRules = require("./type-rules"); const generateDescriptor = require("./generate-descriptor"); const getSchemaKeys = require("./util/get-schema-keys"); const nullMissingFields = require("./util/null-missing-fields"); /* TODO: Traits implementing traits */ module.exports = function createTrait(name, schema, options = {}) { let schemaDescriptors = mapObj(schema, (key, rule) => { return generateDescriptor(rule, key, true, options._registry); }); let schemaKeys = getSchemaKeys(schema); return typeRules._createTypeRule({ _isTrait: true, _registry: options._registry, _name: name, applyImplementation: function (implementation) { /* FIXME: Verify that there are no extraneous keys or unspecified values */ let validatedImplementation = Object.create({ _data: {} }, schemaDescriptors); let implementationWithoutSlots = filterObj(implementation, (key, value) => { return (value == null || value._isSlotRule !== true); }); let nullFields = nullMissingFields(implementation, schemaKeys); Object.assign(validatedImplementation, implementationWithoutSlots, nullFields); // let slotProperties = filterObj(implementation, (key, value) => { // return (value != null && value._isSlotRule === true); // }); // // let slotDescriptors = mapObj(slotProperties, (key, value) => { // return generateDescriptor(schema[key], key); // }); let implementationDescriptors = mapObj(implementation, (key, value) => { if (value != null && value._isSlotRule === true) { return generateDescriptor(schema[key], key, true, options._registry); } else { return generateDescriptor(value, key, false, options._registry); } }); /* FIXME: Get rid of duplication here somehow? */ let slotSchemaKeys = Object.keys(implementation).filter((key) => { let value = implementation[key]; return (value != null && value._isSlotRule != null); }); return {implementationDescriptors, slotSchemaKeys}; } }); };